diff --git a/.gitignore b/.gitignore
index 1f921971d8bb..316cf974e6c1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,11 @@ target/
# Subdirectories in src
src/bash/*
!src/bash/Makefile
+src/dhcpmon/debian/*
+!src/dhcpmon/debian/changelog
+!src/dhcpmon/debian/compat
+!src/dhcpmon/debian/control
+!src/dhcpmon/debian/rules
src/ixgbe/*
!src/ixgbe/Makefile
src/isc-dhcp/*
@@ -50,6 +55,8 @@ src/isc-dhcp/*
!src/isc-dhcp/Makefile
!src/isc-dhcp/patch/
src/libnl3/*
+!src/libnl3/debian
+src/libnl3/debian/libnl-*/
!src/libnl3/Makefile
src/libteam/*
!src/libteam/Makefile
@@ -104,6 +111,7 @@ src/thrift/*
# Autogenerated Dockerfiles
sonic-slave/Dockerfile
sonic-slave-stretch/Dockerfile
+sonic-slave-jessie/Dockerfile
dockers/docker-base/Dockerfile
dockers/docker-base-stretch/Dockerfile
dockers/docker-config-engine/Dockerfile
@@ -140,3 +148,17 @@ src/sonic-daemon-base/sonic_daemon_base.egg-info
# Misc. files
files/initramfs-tools/arista-convertfs
files/initramfs-tools/union-mount
+
+# Debian byproduct files
+src/**/debian/stamp-*/
+src/**/debian/*.log
+src/**/debian/*.substvars
+src/**/debian/.debhelper/
+src/**/debian/tmp/
+src/**/debian/autoreconf.*
+src/**/debian/build/
+src/**/debian/files
+src/**/debian/stamp-autotools-files
+
+# .o files
+src/**/*.o
diff --git a/.gitmodules b/.gitmodules
index b9831ba33296..ca8b4b0098a8 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -75,3 +75,10 @@
[submodule "Switch-SDK-drivers"]
path = platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers
url = https://github.com/Mellanox/Switch-SDK-drivers
+[submodule "src/sonic-restapi"]
+ path = src/sonic-restapi
+ url = https://github.com/Azure/sonic-restapi.git
+ branch = master
+[submodule "src/sonic-ztp"]
+ path = src/sonic-ztp
+ url = https://github.com/Azure/sonic-ztp
diff --git a/Makefile.work b/Makefile.work
index b81ac591246f..e4e31a134555 100644
--- a/Makefile.work
+++ b/Makefile.work
@@ -7,7 +7,9 @@
# * BUILD_NUMBER: Desired version-number to pass to the building-system.
# * ENABLE_DHCP_GRAPH_SERVICE: Enables get-graph service to fetch minigraph files
# through http.
+# * ENABLE_ZTP: Enables zero touch provisioning.
# * SHUTDOWN_BGP_ON_START: Sets admin-down state for all bgp peerings after restart.
+# * INSTALL_KUBERNETES: Allows including Kubernetes
# * ENABLE_PFCWD_ON_START: Enable PFC Watchdog (PFCWD) on server-facing ports
# * by default for TOR switch.
# * ENABLE_SYNCD_RPC: Enables rpc-based syncd builds.
@@ -162,7 +164,12 @@ SONIC_BUILD_INSTRUCTION := make \
BUILD_NUMBER=$(BUILD_NUMBER) \
BUILD_TIMESTAMP=$(BUILD_TIMESTAMP) \
ENABLE_DHCP_GRAPH_SERVICE=$(ENABLE_DHCP_GRAPH_SERVICE) \
+ ENABLE_ZTP=$(ENABLE_ZTP) \
SHUTDOWN_BGP_ON_START=$(SHUTDOWN_BGP_ON_START) \
+ INSTALL_KUBERNETES=$(INSTALL_KUBERNETES) \
+ KUBERNETES_VERSION=$(KUBERNETES_VERSION) \
+ K8s_GCR_IO_PAUSE_VERSION=$(K8s_GCR_IO_PAUSE_VERSION) \
+ K8s_CNI_CALICO_VERSION=$(K8s_CNI_CALICO_VERSION) \
SONIC_ENABLE_PFCWD_ON_START=$(ENABLE_PFCWD_ON_START) \
SONIC_ENABLE_SYNCD_RPC=$(ENABLE_SYNCD_RPC) \
SONIC_INSTALL_DEBUG_TOOLS=$(INSTALL_DEBUG_TOOLS) \
@@ -175,6 +182,7 @@ SONIC_BUILD_INSTRUCTION := make \
HTTP_PROXY=$(http_proxy) \
HTTPS_PROXY=$(https_proxy) \
SONIC_ENABLE_SYSTEM_TELEMETRY=$(ENABLE_SYSTEM_TELEMETRY) \
+ SONIC_ENABLE_RESTAPI=$(ENABLE_RESTAPI) \
EXTRA_JESSIE_TARGETS=$(EXTRA_JESSIE_TARGETS) \
$(SONIC_OVERRIDE_BUILD_VARS)
diff --git a/build_debian.sh b/build_debian.sh
index cf545ff2fe47..fac25f18de6b 100755
--- a/build_debian.sh
+++ b/build_debian.sh
@@ -37,7 +37,7 @@ if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then
else
DOCKER_VERSION=5:18.09.8~3-0~debian-stretch
fi
-LINUX_KERNEL_VERSION=4.9.0-9-2
+LINUX_KERNEL_VERSION=4.9.0-11-2
## Working directory to prepare the file system
FILESYSTEM_ROOT=./fsroot
@@ -139,7 +139,9 @@ sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/initramfs-tools_*.deb || \
sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/linux-image-${LINUX_KERNEL_VERSION}-*_${CONFIGURED_ARCH}.deb || \
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install acl
-[[ $CONFIGURED_ARCH == amd64 ]] && sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install dmidecode
+if [[ $CONFIGURED_ARCH == amd64 ]]; then
+ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install dmidecode hdparm
+fi
## Update initramfs for booting with squashfs+overlay
cat files/initramfs-tools/modules | sudo tee -a $FILESYSTEM_ROOT/etc/initramfs-tools/modules > /dev/null
@@ -201,6 +203,22 @@ sudo LANG=C chroot $FILESYSTEM_ROOT apt-get update
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install docker-ce=${DOCKER_VERSION}
sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y remove software-properties-common gnupg2
+if [ "$INSTALL_KUBERNETES" == "y" ]
+then
+ ## Install Kubernetes
+ echo '[INFO] Install kubernetes'
+ sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT curl -fsSL \
+ https://packages.cloud.google.com/apt/doc/apt-key.gpg | \
+ sudo LANG=C chroot $FILESYSTEM_ROOT apt-key add -
+ ## Check out the sources list update matches current Debian version
+ sudo cp files/image_config/kubernetes/kubernetes.list $FILESYSTEM_ROOT/etc/apt/sources.list.d/
+ sudo LANG=C chroot $FILESYSTEM_ROOT apt-get update
+ sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubeadm=${KUBERNETES_VERSION}-00
+ # kubeadm package auto install kubelet & kubectl
+else
+ echo '[INFO] Skipping Install kubernetes'
+fi
+
## Add docker config drop-in to specify dockerd command line
sudo mkdir -p $FILESYSTEM_ROOT/etc/systemd/system/docker.service.d/
## Note: $_ means last argument of last command
@@ -272,7 +290,8 @@ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y in
cgroup-tools \
ipmitool \
ndisc6 \
- makedumpfile
+ makedumpfile \
+ conntrack
if [[ $CONFIGURED_ARCH == amd64 ]]; then
@@ -314,10 +333,6 @@ fi
## Disable kexec supported reboot which was installed by default
sudo sed -i 's/LOAD_KEXEC=true/LOAD_KEXEC=false/' $FILESYSTEM_ROOT/etc/default/kexec
-## Modifty ntp default configuration: disable initial jump (add -x), and disable
-## jump when time difference is greater than 1000 seconds (remove -g).
-sudo sed -i "s/NTPD_OPTS='-g'/NTPD_OPTS='-x'/" $FILESYSTEM_ROOT/etc/default/ntp
-
## Remove sshd host keys, and will regenerate on first sshd start
sudo rm -f $FILESYSTEM_ROOT/etc/ssh/ssh_host_*_key*
sudo cp files/sshd/host-ssh-keygen.sh $FILESYSTEM_ROOT/usr/local/bin/
@@ -374,6 +389,12 @@ set /files/etc/sysctl.conf/net.ipv4.conf.all.arp_ignore 2
set /files/etc/sysctl.conf/net.ipv4.neigh.default.base_reachable_time_ms 1800000
set /files/etc/sysctl.conf/net.ipv6.neigh.default.base_reachable_time_ms 1800000
+set /files/etc/sysctl.conf/net.ipv4.neigh.default.gc_thresh1 1024
+set /files/etc/sysctl.conf/net.ipv6.neigh.default.gc_thresh1 1024
+set /files/etc/sysctl.conf/net.ipv4.neigh.default.gc_thresh2 2048
+set /files/etc/sysctl.conf/net.ipv6.neigh.default.gc_thresh2 2048
+set /files/etc/sysctl.conf/net.ipv4.neigh.default.gc_thresh3 4096
+set /files/etc/sysctl.conf/net.ipv6.neigh.default.gc_thresh3 4096
set /files/etc/sysctl.conf/net.ipv6.conf.default.forwarding 1
set /files/etc/sysctl.conf/net.ipv6.conf.all.forwarding 1
@@ -387,9 +408,6 @@ set /files/etc/sysctl.conf/net.ipv6.conf.default.keep_addr_on_down 1
set /files/etc/sysctl.conf/net.ipv6.conf.all.keep_addr_on_down 1
set /files/etc/sysctl.conf/net.ipv6.conf.eth0.keep_addr_on_down 1
-set /files/etc/sysctl.conf/net.ipv6.conf.eth0.accept_ra_defrtr 0
-set /files/etc/sysctl.conf/net.ipv6.conf.eth0.accept_ra 0
-
set /files/etc/sysctl.conf/net.ipv4.tcp_l3mdev_accept 1
set /files/etc/sysctl.conf/net.ipv4.udp_l3mdev_accept 1
@@ -424,10 +442,10 @@ EOF
sudo cp files/dhcp/rfc3442-classless-routes $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d
sudo cp files/dhcp/sethostname $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d/
+sudo cp files/dhcp/sethostname6 $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d/
sudo cp files/dhcp/graphserviceurl $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d/
sudo cp files/dhcp/snmpcommunity $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d/
sudo cp files/dhcp/vrf $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d/
-sudo cp files/dhcp/dhclient.conf $FILESYSTEM_ROOT/etc/dhcp/
if [ -f files/image_config/ntp/ntp ]; then
sudo cp ./files/image_config/ntp/ntp $FILESYSTEM_ROOT/etc/init.d/
fi
diff --git a/build_debug_docker_j2.sh b/build_debug_docker_j2.sh
index 3655ac037bd6..0b167cf0f39e 100755
--- a/build_debug_docker_j2.sh
+++ b/build_debug_docker_j2.sh
@@ -28,7 +28,7 @@ debs/{{ deb }}{{' '}}
{% if $3 is defined %}
{% if $3|length %}
-RUN apt-get install -f -y \
+RUN apt-get update && apt-get install -f -y \
{% for dbg in $3.split(' ') -%}
{{ dbg }}{{' '}}
{%- endfor %}
diff --git a/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/sfp.py b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/sfp.py
index 07e0649579ac..be1dbb52a79b 100644
--- a/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/sfp.py
+++ b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/sfp.py
@@ -1111,7 +1111,7 @@ def get_presence(self):
presence = int(sfp_presence.read(), 16)
except IOError:
return False
- logger.log_info("debug:port_ %s sfp presence is %s" % (str(self.index)), % (str(presence))
+ logger.log_info("debug:port_ %s sfp presence is %s" % (str(self.index), str(presence)))
return presence
def get_model(self):
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/AS14-128H/port_config.ini b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/AS14-128H/port_config.ini
new file mode 100644
index 000000000000..224418d2c15a
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/AS14-128H/port_config.ini
@@ -0,0 +1,129 @@
+# name lanes alias index
+Ethernet1 9,10 QSFP1 1
+Ethernet2 11,12 QSFP2 2
+Ethernet3 15,16 QSFP3 3
+Ethernet4 13,14 QSFP4 4
+Ethernet5 77,78 QSFP5 5
+Ethernet6 79,80 QSFP6 6
+Ethernet7 75,76 QSFP7 7
+Ethernet8 73,74 QSFP8 8
+Ethernet9 1,2 QSFP9 9
+Ethernet10 3,4 QSFP10 10
+Ethernet11 7,8 QSFP11 11
+Ethernet12 5,6 QSFP12 12
+Ethernet13 69,70 QSFP13 13
+Ethernet14 71,72 QSFP14 14
+Ethernet15 67,68 QSFP15 15
+Ethernet16 65,66 QSFP16 16
+Ethernet17 41,42 QSFP17 17
+Ethernet18 43,44 QSFP18 18
+Ethernet19 47,48 QSFP19 19
+Ethernet20 45,46 QSFP20 20
+Ethernet21 109,110 QSFP21 21
+Ethernet22 111,112 QSFP22 22
+Ethernet23 107,108 QSFP23 23
+Ethernet24 105,106 QSFP24 24
+Ethernet25 33,34 QSFP25 25
+Ethernet26 35,36 QSFP26 26
+Ethernet27 39,40 QSFP27 27
+Ethernet28 37,38 QSFP28 28
+Ethernet29 101,102 QSFP29 29
+Ethernet30 103,104 QSFP30 30
+Ethernet31 99,100 QSFP31 31
+Ethernet32 97,98 QSFP32 32
+Ethernet33 137,138 QSFP33 33
+Ethernet34 139,140 QSFP34 34
+Ethernet35 143,144 QSFP35 35
+Ethernet36 141,142 QSFP36 36
+Ethernet37 205,206 QSFP37 37
+Ethernet38 207,208 QSFP38 38
+Ethernet39 203,204 QSFP39 39
+Ethernet40 201,202 QSFP40 40
+Ethernet41 129,130 QSFP41 41
+Ethernet42 131,132 QSFP42 42
+Ethernet43 135,136 QSFP43 43
+Ethernet44 133,134 QSFP44 44
+Ethernet45 197,198 QSFP45 45
+Ethernet46 199,200 QSFP46 46
+Ethernet47 195,196 QSFP47 47
+Ethernet48 193,194 QSFP48 48
+Ethernet49 169,170 QSFP49 49
+Ethernet50 171,172 QSFP50 50
+Ethernet51 175,176 QSFP51 51
+Ethernet52 173,174 QSFP52 52
+Ethernet53 237,238 QSFP53 53
+Ethernet54 239,240 QSFP54 54
+Ethernet55 235,236 QSFP55 55
+Ethernet56 233,234 QSFP56 56
+Ethernet57 161,162 QSFP57 57
+Ethernet58 163,164 QSFP58 58
+Ethernet59 167,168 QSFP59 59
+Ethernet60 165,166 QSFP60 60
+Ethernet61 229,230 QSFP61 61
+Ethernet62 231,232 QSFP62 62
+Ethernet63 227,228 QSFP63 63
+Ethernet64 225,226 QSFP64 64
+Ethernet65 25,26 QSFP65 65
+Ethernet66 27,28 QSFP66 66
+Ethernet67 31,32 QSFP67 67
+Ethernet68 29,30 QSFP68 68
+Ethernet69 93,94 QSFP69 69
+Ethernet70 95,96 QSFP70 70
+Ethernet71 91,92 QSFP71 71
+Ethernet72 89,90 QSFP72 72
+Ethernet73 17,18 QSFP73 73
+Ethernet74 19,20 QSFP74 74
+Ethernet75 23,24 QSFP75 75
+Ethernet76 21,22 QSFP76 76
+Ethernet77 85,86 QSFP77 77
+Ethernet78 87,88 QSFP78 78
+Ethernet79 83,84 QSFP79 79
+Ethernet80 81,82 QSFP80 80
+Ethernet81 57,58 QSFP81 81
+Ethernet82 59,60 QSFP82 82
+Ethernet83 63,64 QSFP83 83
+Ethernet84 61,62 QSFP84 84
+Ethernet85 125,126 QSFP85 85
+Ethernet86 127,128 QSFP86 86
+Ethernet87 123,124 QSFP87 87
+Ethernet88 121,122 QSFP88 88
+Ethernet89 49,50 QSFP89 89
+Ethernet90 51,52 QSFP90 90
+Ethernet91 55,56 QSFP91 91
+Ethernet92 53,54 QSFP92 92
+Ethernet93 117,118 QSFP93 93
+Ethernet94 119,120 QSFP94 94
+Ethernet95 115,116 QSFP95 95
+Ethernet96 113,114 QSFP96 96
+Ethernet97 153,154 QSFP97 97
+Ethernet98 155,156 QSFP98 98
+Ethernet99 159,160 QSFP99 99
+Ethernet100 157,158 QSFP100 100
+Ethernet101 221,222 QSFP101 101
+Ethernet102 223,224 QSFP102 102
+Ethernet103 219,220 QSFP103 103
+Ethernet104 217,218 QSFP104 104
+Ethernet105 145,146 QSFP105 105
+Ethernet106 147,148 QSFP106 106
+Ethernet107 151,152 QSFP107 107
+Ethernet108 149,150 QSFP108 108
+Ethernet109 213,214 QSFP109 109
+Ethernet110 215,216 QSFP110 110
+Ethernet111 211,212 QSFP111 111
+Ethernet112 209,210 QSFP112 112
+Ethernet113 185,186 QSFP113 113
+Ethernet114 187,188 QSFP114 114
+Ethernet115 191,192 QSFP115 115
+Ethernet116 189,190 QSFP116 116
+Ethernet117 253,254 QSFP117 117
+Ethernet118 255,256 QSFP118 118
+Ethernet119 251,252 QSFP119 119
+Ethernet120 249,250 QSFP120 120
+Ethernet121 177,178 QSFP121 121
+Ethernet122 179,180 QSFP122 122
+Ethernet123 183,184 QSFP123 123
+Ethernet124 181,182 QSFP124 124
+Ethernet125 245,246 QSFP125 125
+Ethernet126 247,248 QSFP126 126
+Ethernet127 243,244 QSFP127 127
+Ethernet128 241,242 QSFP128 128
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/AS14-128H/sai.profile b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/AS14-128H/sai.profile
new file mode 100644
index 000000000000..f2db109d7afc
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/AS14-128H/sai.profile
@@ -0,0 +1 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/th3-as14-128h.config.bcm
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/custom_led.bin b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/custom_led.bin
new file mode 100644
index 000000000000..a7f256cadee8
Binary files /dev/null and b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/custom_led.bin differ
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/default_sku b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/default_sku
new file mode 100644
index 000000000000..30e5af958eb9
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/default_sku
@@ -0,0 +1 @@
+AS23-128H t1
\ No newline at end of file
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/installer.conf b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/installer.conf
new file mode 100644
index 000000000000..dc3cf67d19e7
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/installer.conf
@@ -0,0 +1,2 @@
+CONSOLE_SPEED=9600
+ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="processor.max_cstate=1 intel_idle.max_cstate=0"
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/led_proc_init.soc b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/led_proc_init.soc
new file mode 100644
index 000000000000..28cd4b9bc9f7
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/led_proc_init.soc
@@ -0,0 +1,9 @@
+#Enable all ports
+#port all en=1
+#sleep 6
+#linkscan 250000; port xe,ce linkscan=on
+
+#Load LED
+#led auto on; led start
+
+
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/linkscan_led_fw.bin b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/linkscan_led_fw.bin
new file mode 100644
index 000000000000..c2fa94a2d8cb
Binary files /dev/null and b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/linkscan_led_fw.bin differ
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/minigraph.xml b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/minigraph.xml
new file mode 100644
index 000000000000..500be59307a0
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/minigraph.xml
@@ -0,0 +1,1333 @@
+
+
+
+
+
+ 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
+
+
+
+
+
+ QSFP1
+ 10.0.0.0/31
+
+
+
+ QSFP2
+ 10.0.0.2/31
+
+
+
+ QSFP3
+ 10.0.0.4/31
+
+
+
+ QSFP4
+ 10.0.0.6/31
+
+
+
+ QSFP5
+ 10.0.0.8/31
+
+
+
+ QSFP6
+ 10.0.0.10/31
+
+
+
+ QSFP7
+ 10.0.0.12/31
+
+
+
+ QSFP8
+ 10.0.0.14/31
+
+
+
+ QSFP9
+ 10.0.0.16/31
+
+
+
+ QSFP10
+ 10.0.0.18/31
+
+
+
+ QSFP11
+ 10.0.0.20/31
+
+
+
+ QSFP12
+ 10.0.0.22/31
+
+
+
+ QSFP13
+ 10.0.0.24/31
+
+
+
+ QSFP14
+ 10.0.0.26/31
+
+
+
+ QSFP15
+ 10.0.0.28/31
+
+
+
+ QSFP16
+ 10.0.0.30/31
+
+
+
+ QSFP17
+ 10.0.0.32/31
+
+
+
+ QSFP18
+ 10.0.0.34/31
+
+
+
+ QSFP19
+ 10.0.0.36/31
+
+
+
+ QSFP20
+ 10.0.0.38/31
+
+
+
+ QSFP21
+ 10.0.0.40/31
+
+
+
+ QSFP22
+ 10.0.0.42/31
+
+
+
+ QSFP23
+ 10.0.0.44/31
+
+
+
+ QSFP24
+ 10.0.0.46/31
+
+
+
+ QSFP25
+ 10.0.0.48/31
+
+
+
+ QSFP26
+ 10.0.0.50/31
+
+
+
+ QSFP27
+ 10.0.0.52/31
+
+
+
+ QSFP28
+ 10.0.0.54/31
+
+
+
+ QSFP29
+ 10.0.0.56/31
+
+
+
+ QSFP30
+ 10.0.0.58/31
+
+
+
+ QSFP31
+ 10.0.0.60/31
+
+
+
+ QSFP32
+ 10.0.0.62/31
+
+
+
+ QSFP33
+ 10.0.0.64/31
+
+
+
+ QSFP34
+ 10.0.0.66/31
+
+
+
+ QSFP35
+ 10.0.0.68/31
+
+
+
+ QSFP36
+ 10.0.0.70/31
+
+
+
+ QSFP37
+ 10.0.0.72/31
+
+
+
+ QSFP38
+ 10.0.0.74/31
+
+
+
+ QSFP39
+ 10.0.0.76/31
+
+
+
+ QSFP40
+ 10.0.0.78/31
+
+
+
+ QSFP41
+ 10.0.0.80/31
+
+
+
+ QSFP42
+ 10.0.0.82/31
+
+
+
+ QSFP43
+ 10.0.0.84/31
+
+
+
+ QSFP44
+ 10.0.0.86/31
+
+
+
+ QSFP45
+ 10.0.0.88/31
+
+
+
+ QSFP46
+ 10.0.0.90/31
+
+
+
+ QSFP47
+ 10.0.0.92/31
+
+
+
+ QSFP48
+ 10.0.0.94/31
+
+
+
+ QSFP49
+ 10.0.0.96/31
+
+
+
+ QSFP50
+ 10.0.0.98/31
+
+
+
+ QSFP51
+ 10.0.0.100/31
+
+
+
+ QSFP52
+ 10.0.0.102/31
+
+
+
+ QSFP53
+ 10.0.0.104/31
+
+
+
+ QSFP54
+ 10.0.0.106/31
+
+
+
+ QSFP55
+ 10.0.0.108/31
+
+
+
+ QSFP56
+ 10.0.0.110/31
+
+
+
+ QSFP57
+ 10.0.0.112/31
+
+
+
+ QSFP58
+ 10.0.0.114/31
+
+
+
+ QSFP59
+ 10.0.0.116/31
+
+
+
+ QSFP60
+ 10.0.0.118/31
+
+
+
+ QSFP61
+ 10.0.0.120/31
+
+
+
+ QSFP62
+ 10.0.0.122/31
+
+
+
+ QSFP63
+ 10.0.0.124/31
+
+
+
+ QSFP64
+ 10.0.0.126/31
+
+
+
+ QSFP65
+ 10.0.1.0/31
+
+
+
+ QSFP66
+ 10.0.1.2/31
+
+
+
+ QSFP67
+ 10.0.1.4/31
+
+
+
+ QSFP68
+ 10.0.1.6/31
+
+
+
+ QSFP69
+ 10.0.1.8/31
+
+
+
+ QSFP70
+ 10.0.1.10/31
+
+
+
+ QSFP71
+ 10.0.1.12/31
+
+
+
+ QSFP72
+ 10.0.1.14/31
+
+
+
+ QSFP73
+ 10.0.1.16/31
+
+
+
+ QSFP74
+ 10.0.1.18/31
+
+
+
+ QSFP75
+ 10.0.1.20/31
+
+
+
+ QSFP76
+ 10.0.1.22/31
+
+
+
+ QSFP77
+ 10.0.1.24/31
+
+
+
+ QSFP78
+ 10.0.1.26/31
+
+
+
+ QSFP79
+ 10.0.1.28/31
+
+
+
+ QSFP80
+ 10.0.1.30/31
+
+
+
+ QSFP81
+ 10.0.1.32/31
+
+
+
+ QSFP82
+ 10.0.1.34/31
+
+
+
+ QSFP83
+ 10.0.1.36/31
+
+
+
+ QSFP84
+ 10.0.1.38/31
+
+
+
+ QSFP85
+ 10.0.1.40/31
+
+
+
+ QSFP86
+ 10.0.1.42/31
+
+
+
+ QSFP87
+ 10.0.1.44/31
+
+
+
+ QSFP88
+ 10.0.1.46/31
+
+
+
+ QSFP89
+ 10.0.1.48/31
+
+
+
+ QSFP90
+ 10.0.1.50/31
+
+
+
+ QSFP91
+ 10.0.1.52/31
+
+
+
+ QSFP92
+ 10.0.1.54/31
+
+
+
+ QSFP93
+ 10.0.1.56/31
+
+
+
+ QSFP94
+ 10.0.1.58/31
+
+
+
+ QSFP95
+ 10.0.1.60/31
+
+
+
+ QSFP96
+ 10.0.1.62/31
+
+
+
+ QSFP97
+ 10.0.1.64/31
+
+
+
+ QSFP98
+ 10.0.1.66/31
+
+
+
+ QSFP99
+ 10.0.1.68/31
+
+
+
+ QSFP100
+ 10.0.1.70/31
+
+
+
+ QSFP101
+ 10.0.1.72/31
+
+
+
+ QSFP102
+ 10.0.1.74/31
+
+
+
+ QSFP103
+ 10.0.1.76/31
+
+
+
+ QSFP104
+ 10.0.1.78/31
+
+
+
+ QSFP105
+ 10.0.1.80/31
+
+
+
+ QSFP106
+ 10.0.1.82/31
+
+
+
+ QSFP107
+ 10.0.1.84/31
+
+
+
+ QSFP108
+ 10.0.1.86/31
+
+
+
+ QSFP109
+ 10.0.1.88/31
+
+
+
+ QSFP110
+ 10.0.1.90/31
+
+
+
+ QSFP111
+ 10.0.1.92/31
+
+
+
+ QSFP112
+ 10.0.1.94/31
+
+
+
+ QSFP113
+ 10.0.1.96/31
+
+
+
+ QSFP114
+ 10.0.1.98/31
+
+
+
+ QSFP115
+ 10.0.1.100/31
+
+
+
+ QSFP116
+ 10.0.1.102/31
+
+
+
+ QSFP117
+ 10.0.1.104/31
+
+
+
+ QSFP118
+ 10.0.1.106/31
+
+
+
+ QSFP119
+ 10.0.1.108/31
+
+
+
+ QSFP120
+ 10.0.1.110/31
+
+
+
+ QSFP121
+ 10.0.1.112/31
+
+
+
+ QSFP122
+ 10.0.1.114/31
+
+
+
+ QSFP123
+ 10.0.1.116/31
+
+
+
+ QSFP124
+ 10.0.1.118/31
+
+
+
+ QSFP125
+ 10.0.1.120/31
+
+
+
+ QSFP126
+ 10.0.1.122/31
+
+
+
+ QSFP127
+ 10.0.1.124/31
+
+
+
+ QSFP128
+ 10.0.1.126/31
+
+
+
+
+
+
+
+
+
+
+
+ sonic
+ AS14-128H
+
+
+
+
+
+
+ sonic
+
+
+ DhcpResources
+
+
+
+
+ NtpResources
+
+ 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org
+
+
+ SyslogResources
+
+
+
+
+ ErspanDestinationIpv4
+
+ 2.2.2.2
+
+
+
+
+
+
+ sonic
+ AS14-128H
+
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/opennsl-postinit.cfg b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/opennsl-postinit.cfg
new file mode 100644
index 000000000000..7008c14c0ffc
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/opennsl-postinit.cfg
@@ -0,0 +1,3 @@
+linkscan 250000; port xe,ce linkscan=on
+sleep 1
+led auto on; led start
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/cputemputil.py b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/cputemputil.py
new file mode 100644
index 000000000000..ac2589d044fd
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/cputemputil.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+#
+# cputemputil.py
+#
+# Platform-specific CPU temperature Interface for SONiC
+#
+
+__author__ = 'Wirut G.'
+__license__ = "GPL"
+__version__ = "0.1.0"
+__status__ = "Development"
+
+
+import subprocess
+import requests
+
+
+class CpuTempUtil():
+ """Platform-specific CpuTempUtil class"""
+
+ def __init__(self):
+ pass
+
+ def get_cpu_temp(self):
+
+ # Get list of temperature of CPU cores.
+ p = subprocess.Popen(['sensors', '-Au', 'coretemp-isa-0000'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ raw_data_list = out.splitlines()
+ temp_string_list = [i for i, s in enumerate(
+ raw_data_list) if '_input' in s]
+ tmp_list = [0]
+
+ for temp_string in temp_string_list:
+ tmp_list.append(float(raw_data_list[temp_string].split(":")[1]))
+
+ return tmp_list
+
+ def get_max_cpu_tmp(self):
+ # Get maximum temperature from list of temperature of CPU cores.
+ return max(self.get_cpu_temp())
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/eeprom.py b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/eeprom.py
new file mode 100644
index 000000000000..46559439061d
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/eeprom.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Celestica PHALANX
+#
+# Platform and model specific eeprom subclass, inherits from the base class,
+# and provides the followings:
+# - the eeprom format definition
+# - specific encoder/decoder if there is special need
+#############################################################################
+
+try:
+ from sonic_eeprom import eeprom_tlvinfo
+except ImportError, e:
+ raise ImportError (str(e) + "- required module not found")
+
+
+class board(eeprom_tlvinfo.TlvInfoDecoder):
+
+ def __init__(self, name, path, cpld_root, ro):
+ self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom"
+ super(board, self).__init__(self.eeprom_path, 0, '', True)
+
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/fanutil.py b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/fanutil.py
new file mode 100644
index 000000000000..7c37088b927e
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/fanutil.py
@@ -0,0 +1,309 @@
+#!/usr/bin/env python
+
+__author__ = 'Wirut G.'
+__license__ = "GPL"
+__version__ = "0.1.2"
+__status__ = "Development"
+
+import requests
+import re
+
+
+class FanUtil():
+ """Platform-specific FanUtil class"""
+
+ def __init__(self):
+
+ self.fan_fru_url = "http://240.1.1.1:8080/api/sys/fruid/fan"
+ self.sensor_url = "http://240.1.1.1:8080/api/sys/sensors"
+ self.fru_data_list = None
+ self.sensor_data_list = None
+
+ def request_data(self):
+ # Reqest data from BMC if not exist.
+ if self.fru_data_list is None or self.sensor_data_list is None:
+ fru_data_req = requests.get(self.fan_fru_url)
+ sensor_data_req = requests.get(self.sensor_url)
+ fru_json = fru_data_req.json()
+ sensor_json = sensor_data_req.json()
+ self.fru_data_list = fru_json.get('Information')
+ self.sensor_data_list = sensor_json.get('Information')
+ return self.fru_data_list, self.sensor_data_list
+
+ def name_to_index(self, fan_name):
+ # Get fan index from fan name
+ match = re.match(r"(FAN)([0-9]+)-(1|2)", fan_name, re.I)
+ fan_index = None
+ if match:
+ i_list = list(match.groups())
+ fan_index = int(i_list[1])*2 - (int(i_list[2]) % 2)
+ return fan_index
+
+ def get_num_fans(self):
+ """
+ Get the number of fans
+ :return: int num_fans
+ """
+ num_fans = 10
+
+ return num_fans
+
+ def get_fan_speed(self, fan_name):
+ """
+ Get the current speed of the fan, the unit is "RPM"
+ :return: int fan_speed
+ """
+
+ try:
+ # Get real fan index
+ index = self.name_to_index(fan_name)
+
+ # Set key and index.
+ fan_speed = 0
+ position_key = "Front" if index % 2 != 0 else "Rear"
+ index = int(round(float(index)/2))
+ fan_key = "Fan " + str(index) + " " + position_key
+
+ # Request and validate fan information.
+ self.fru_data_list, self.sensor_data_list = self.request_data()
+
+ # Get fan's speed.
+ for sensor_data in self.sensor_data_list:
+ sensor_name = sensor_data.get('name')
+ if "fan" in str(sensor_name):
+ fan_data = sensor_data.get(fan_key)
+ fan_sp_list = map(int, re.findall(r'\d+', fan_data))
+ fan_speed = fan_sp_list[0]
+
+ except:
+ return 0
+
+ return fan_speed
+
+ def get_fan_low_threshold(self, fan_name):
+ """
+ Get the low speed threshold of the fan.
+ if the current speed < low speed threshold,
+ the status of the fan is not ok.
+ :return: int fan_low_threshold
+ """
+
+ try:
+ # Get real fan index
+ index = self.name_to_index(fan_name)
+
+ # Set key and index.
+ fan_low_threshold = 0
+ position_key = "Front" if index % 2 != 0 else "Rear"
+ index = int(round(float(index)/2))
+ fan_key = "Fan " + str(index) + " " + position_key
+
+ # Request and validate fan information.
+ self.fru_data_list, self.sensor_data_list = self.request_data()
+
+ # Get fan's threshold.
+ for sensor_data in self.sensor_data_list:
+ sensor_name = sensor_data.get('name')
+ if "fan" in str(sensor_name):
+ fan_data = sensor_data.get(fan_key)
+ fan_sp_list = map(int, re.findall(r'\d+', fan_data))
+ fan_low_threshold = fan_sp_list[1]
+
+ except:
+ return "N/A"
+
+ return fan_low_threshold
+
+ def get_fan_high_threshold(self, fan_name):
+ """
+ Get the hight speed threshold of the fan,
+ if the current speed > high speed threshold,
+ the status of the fan is not ok
+ :return: int fan_high_threshold
+ """
+
+ try:
+ # Get real fan index
+ index = self.name_to_index(fan_name)
+
+ # Set key and index.
+ fan_high_threshold = 0
+ position_key = "Front" if index % 2 != 0 else "Rear"
+ index = int(round(float(index)/2))
+ fan_key = "Fan " + str(index) + " " + position_key
+
+ # Request and validate fan information.
+ self.fru_data_list, self.sensor_data_list = self.request_data()
+
+ # Get fan's threshold.
+ for sensor_data in self.sensor_data_list:
+ sensor_name = sensor_data.get('name')
+ if "fan" in str(sensor_name):
+ fan_data = sensor_data.get(fan_key)
+ fan_sp_list = map(int, re.findall(r'\d+', fan_data))
+ fan_high_threshold = fan_sp_list[2]
+
+ except:
+ return 0
+
+ return fan_high_threshold
+
+ def get_fan_pn(self, fan_name):
+ """
+ Get the product name of the fan
+ :return: str fan_pn
+ """
+
+ try:
+ # Get real fan index
+ index = self.name_to_index(fan_name)
+
+ # Set key and index.
+ fan_pn = "N/A"
+ index = int(round(float(index)/2))
+ fan_fru_key = "Fantray" + str(index)
+
+ # Request and validate fan information.
+ self.fru_data_list, self.sensor_data_list = self.request_data()
+
+ # Get fan's fru.
+ for fan_fru in self.fru_data_list:
+ matching_fan = [s for s in fan_fru if fan_fru_key in s]
+ if matching_fan:
+ pn = [s for s in fan_fru if "Part" in s]
+ fan_pn = pn[0].split()[4]
+
+ except:
+ return "N/A"
+
+ return fan_pn
+
+ def get_fan_sn(self, fan_name):
+ """
+ Get the serial number of the fan
+ :return: str fan_sn
+ """
+ try:
+ # Get real fan index
+ index = self.name_to_index(fan_name)
+
+ # Set key and index.
+ fan_sn = "N/A"
+ index = int(round(float(index)/2))
+ fan_fru_key = "Fantray" + str(index)
+
+ # Request and validate fan information.
+ self.fru_data_list, self.sensor_data_list = self.request_data()
+
+ # Get fan's fru.
+ for fan_fru in self.fru_data_list:
+ matching_fan = [s for s in fan_fru if fan_fru_key in s]
+ if matching_fan:
+ serial = [s for s in fan_fru if "Serial" in s]
+ fan_sn = serial[0].split()[3]
+
+ except:
+ return "N/A"
+
+ return fan_sn
+
+ def get_fans_name_list(self):
+ """
+ Get list of fan name.
+ :return: list fan_names
+ """
+ fan_names = []
+
+ # Get the number of fans
+ n_fan = self.get_num_fans()
+
+ # Set fan name and add to the list.
+ for x in range(1, n_fan + 1):
+ f_index = int(round(float(x)/2))
+ pos = 1 if x % 2 else 2
+ fan_name = 'FAN{}_{}'.format(f_index, pos)
+ fan_names.append(fan_name)
+
+ return fan_names
+
+ def get_all(self):
+ """
+ Get all information of system FANs, returns JSON objects in python 'DICT'.
+ Number, mandatory, max number of FAN, integer
+ FAN1_1, FAN1_2, ... mandatory, FAN name, string
+ Present, mandatory for each FAN, present status, boolean, True for present, False for NOT present, read directly from h/w
+ Running, conditional, if PRESENT is True, running status of the FAN, True for running, False for stopped, read directly from h/w
+ Speed, conditional, if PRESENT is True, real FAN speed, float, read directly from h/w
+ LowThd, conditional, if PRESENT is True, lower bound of FAN speed, float, read from h/w
+ HighThd, conditional, if PRESENT is True, upper bound of FAN speed, float, read from h/w
+ PN, conditional, if PRESENT is True, PN of the FAN, string
+ SN, conditional, if PRESENT is True, SN of the FAN, string)
+ """
+
+ self.fru_data_list, self.sensor_data_list = self.request_data()
+ all_fan_dict = dict()
+
+ # Get the number of fans
+ n_fan = self.get_num_fans()
+ all_fan_dict["Number"] = n_fan
+
+ # Set fan FRU data.
+ fan_fru_dict = dict()
+ fan_raw_idx = 1
+ for fan_fru in self.fru_data_list:
+ fru_dict = dict()
+ fan_ps = False
+
+ if len(fan_fru) == 0:
+ fan_idx = fan_raw_idx
+ fan_pn = "N/A"
+ fan_sn = "N/A"
+ else:
+ fan_key = fan_fru[0].split()
+ if str(fan_key[-1]).lower() == "absent":
+ fan_idx = int(re.findall('\d+', fan_key[0])[0])
+
+ else:
+ fan_idx = int(re.findall('\d+', fan_key[-1])[0])
+ fan_ps = True
+ pn = [s for s in fan_fru if "Part" in s]
+ sn = [s for s in fan_fru if "Serial" in s]
+ fan_pn = pn[0].split(
+ ":")[-1].strip() if len(pn) > 0 else 'N/A'
+ fan_sn = sn[0].split(
+ ":")[-1].strip() if len(sn) > 0 else 'N/A'
+
+ fru_dict["PN"] = "N/A" if not fan_pn or fan_pn == "" else fan_pn
+ fru_dict["SN"] = "N/A" if not fan_sn or fan_sn == "" else fan_sn
+ fru_dict["Present"] = fan_ps
+ fan_fru_dict[fan_idx] = fru_dict
+ fan_raw_idx += 1
+
+ # Set fan sensor data.
+ for sensor_data in self.sensor_data_list:
+ sensor_name = sensor_data.get('name')
+ if "fan" in str(sensor_name):
+ for x in range(1, n_fan + 1):
+ fan_dict = dict()
+ f_index = int(round(float(x)/2))
+ pos = 1 if x % 2 else 2
+ position_key = "Front" if x % 2 != 0 else "Rear"
+ fan_key = "Fan " + str(f_index) + " " + position_key
+ fan_data = sensor_data.get(fan_key)
+ fan_sp_list = map(int, re.findall(r'\d+', fan_data))
+ fan_dict["Present"] = fan_fru_dict[f_index]["Present"]
+ if fan_dict["Present"] or fan_sp_list[0] > 0:
+ fan_dict["Present"] = True
+ fan_dict["Speed"] = fan_sp_list[0]
+ fan_dict["Running"] = True if fan_dict["Speed"] > 0 else False
+ fan_dict["LowThd"] = fan_sp_list[1]
+ fan_dict["HighThd"] = fan_sp_list[2]
+ fan_dict["PN"] = fan_fru_dict[f_index]["PN"]
+ fan_dict["SN"] = fan_fru_dict[f_index]["SN"]
+ fan_dict["AirFlow"] = "FTOB" if "R1240-G0009" in fan_dict["PN"] else "Unknown"
+ fan_dict["Status"] = True if fan_dict["AirFlow"] != "Unknown" else False
+ fan_name = 'FAN{}_{}'.format(f_index, pos)
+ all_fan_dict[fan_name] = fan_dict
+ break
+
+ return all_fan_dict
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/fwmgrutil.py b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/fwmgrutil.py
new file mode 100644
index 000000000000..619aa7b173f3
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/fwmgrutil.py
@@ -0,0 +1,882 @@
+# fwmgrutil.py
+#
+# Platform-specific firmware management interface for SONiC
+#
+
+import subprocess
+import requests
+import os
+import pexpect
+import base64
+import time
+import json
+import logging
+import ast
+from datetime import datetime
+
+try:
+ from sonic_fwmgr.fwgmr_base import FwMgrUtilBase
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
+
+
+class FwMgrUtil(FwMgrUtilBase):
+
+ """Platform-specific FwMgrUtil class"""
+
+ def __init__(self):
+ self.platform_name = "AS23128h"
+ self.onie_config_file = "/host/machine.conf"
+ self.bmc_info_url = "http://240.1.1.1:8080/api/sys/bmc"
+ self.bmc_raw_command_url = "http://240.1.1.1:8080/api/sys/raw"
+ self.fw_upgrade_url = "http://240.1.1.1:8080/api/sys/upgrade"
+ self.onie_config_file = "/host/machine.conf"
+ self.fw_upgrade_logger_path = "/var/log/fw_upgrade.log"
+ self.cpldb_version_path = "/sys/devices/platform/%s.cpldb/getreg" % self.platform_name
+ self.fpga_version_path = "/sys/devices/platform/%s.switchboard/FPGA/getreg" % self.platform_name
+ self.switchboard_cpld1_path = "/sys/devices/platform/%s.switchboard/CPLD1/getreg" % self.platform_name
+ self.switchboard_cpld2_path = "/sys/devices/platform/%s.switchboard/CPLD2/getreg" % self.platform_name
+ self.switchboard_cpld3_path = "/sys/devices/platform/%s.switchboard/CPLD3/getreg" % self.platform_name
+ self.switchboard_cpld4_path = "/sys/devices/platform/%s.switchboard/CPLD4/getreg" % self.platform_name
+ self.bmc_pwd_path = "/usr/local/etc/bmcpwd"
+
+ def __get_register_value(self, path, register):
+ cmd = "echo {1} > {0}; cat {0}".format(path, register)
+ p = subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ raw_data, err = p.communicate()
+ if err is not '':
+ return 'None'
+ else:
+ return raw_data.strip()
+
+ def __update_fw_upgrade_logger(self, header, message):
+ if not os.path.isfile(self.fw_upgrade_logger_path):
+ cmd = "sudo touch %s && sudo chmod +x %s" % (
+ self.fw_upgrade_logger_path, self.fw_upgrade_logger_path)
+ subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ logging.basicConfig(filename=self.fw_upgrade_logger_path,
+ filemode='a',
+ format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
+ datefmt='%b %d %H:%M:%S',
+ level=logging.INFO)
+
+ log_message = "%s : %s" % (header, message)
+ if header != "last_upgrade_result":
+ print(log_message)
+ return logging.info(log_message)
+
+ def get_bmc_pass(self):
+ if os.path.exists(self.bmc_pwd_path):
+ with open(self.bmc_pwd_path) as file:
+ data = file.read()
+
+ key = "bmc"
+ dec = []
+ enc = base64.urlsafe_b64decode(data)
+ for i in range(len(enc)):
+ key_c = key[i % len(key)]
+ dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
+ dec.append(dec_c)
+ return "".join(dec)
+ return False
+
+ def get_bmc_version(self):
+ """Get BMC version from SONiC
+ :returns: version string
+
+ """
+ bmc_version = None
+
+ bmc_version_key = "OpenBMC Version"
+ bmc_info_req = requests.get(self.bmc_info_url, timeout=60)
+ if bmc_info_req.status_code == 200:
+ bmc_info_json = bmc_info_req.json()
+ bmc_info = bmc_info_json.get('Information')
+ bmc_version = bmc_info.get(bmc_version_key)
+ return str(bmc_version)
+
+ def upload_file_bmc(self, fw_path):
+ scp_command = 'sudo scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -r %s root@240.1.1.1:/home/root/' % os.path.abspath(
+ fw_path)
+ child = pexpect.spawn(scp_command)
+ i = child.expect(["root@240.1.1.1's password:"], timeout=30)
+ bmc_pwd = self.get_bmc_pass()
+ if i == 0 and bmc_pwd:
+ child.sendline(bmc_pwd)
+ data = child.read()
+ print(data)
+ child.close
+ return os.path.isfile(fw_path)
+ return False
+
+ def get_cpld_version(self):
+ """Get CPLD version from SONiC
+ :returns: dict like {'CPLD_1': version_string, 'CPLD_2': version_string}
+ """
+
+ CPLD_B = self.__get_register_value(self.cpldb_version_path, '0xA100')
+ CPLD_C = self.__get_register_value(self.cpldb_version_path, '0xA1E0')
+ CPLD_1 = self.__get_register_value(self.switchboard_cpld1_path, '0x00')
+ CPLD_2 = self.__get_register_value(self.switchboard_cpld2_path, '0x00')
+ CPLD_3 = self.__get_register_value(self.switchboard_cpld3_path, '0x00')
+ CPLD_4 = self.__get_register_value(self.switchboard_cpld4_path, '0x00')
+
+ fan_cpld_key = "FanCPLD Version"
+ fan_cpld = None
+ bmc_info_req = requests.get(self.bmc_info_url)
+ if bmc_info_req.status_code == 200:
+ bmc_info_json = bmc_info_req.json()
+ bmc_info = bmc_info_json.get('Information')
+ fan_cpld = bmc_info.get(fan_cpld_key)
+
+ CPLD_B = 'None' if CPLD_B is 'None' else "{}.{}".format(
+ int(CPLD_B[2], 16), int(CPLD_B[3], 16))
+ CPLD_C = 'None' if CPLD_C is 'None' else "{}.{}".format(
+ int(CPLD_C[2], 16), int(CPLD_C[3], 16))
+ CPLD_1 = 'None' if CPLD_1 is 'None' else "{}.{}".format(
+ int(CPLD_1[2], 16), int(CPLD_1[3], 16))
+ CPLD_2 = 'None' if CPLD_2 is 'None' else "{}.{}".format(
+ int(CPLD_2[2], 16), int(CPLD_2[3], 16))
+ CPLD_3 = 'None' if CPLD_3 is 'None' else "{}.{}".format(
+ int(CPLD_3[2], 16), int(CPLD_3[3], 16))
+ CPLD_4 = 'None' if CPLD_4 is 'None' else "{}.{}".format(
+ int(CPLD_4[2], 16), int(CPLD_4[3], 16))
+ FAN_CPLD = 'None' if fan_cpld is None else "{}.{}".format(
+ int(fan_cpld[0], 16), int(fan_cpld[1], 16))
+
+ cpld_version_dict = {}
+ cpld_version_dict.update({'CPLD_B': CPLD_B})
+ cpld_version_dict.update({'CPLD_C': CPLD_C})
+ cpld_version_dict.update({'CPLD_1': CPLD_1})
+ cpld_version_dict.update({'CPLD_2': CPLD_2})
+ cpld_version_dict.update({'CPLD_3': CPLD_3})
+ cpld_version_dict.update({'CPLD_4': CPLD_4})
+ cpld_version_dict.update({'CPLD_FAN': FAN_CPLD})
+
+ return cpld_version_dict
+
+ def get_bios_version(self):
+ """Get BIOS version from SONiC
+ :returns: version string
+
+ """
+ bios_version = None
+
+ p = subprocess.Popen(
+ ["sudo", "dmidecode", "-s", "bios-version"], stdout=subprocess.PIPE)
+ raw_data = str(p.communicate()[0])
+ if raw_data == '':
+ return str(None)
+ raw_data_list = raw_data.split("\n")
+ bios_version = raw_data_list[0] if len(
+ raw_data_list) == 1 else raw_data_list[-2]
+
+ return str(bios_version)
+
+ def get_onie_version(self):
+ """Get ONiE version from SONiC
+ :returns: version string
+
+ """
+ onie_verison = None
+
+ onie_version_keys = "onie_version"
+ onie_config_file = open(self.onie_config_file, "r")
+ for line in onie_config_file.readlines():
+ if onie_version_keys in line:
+ onie_version_raw = line.split('=')
+ onie_verison = onie_version_raw[1].strip()
+ break
+ onie_config_file.close()
+ return str(onie_verison)
+
+ def get_pcie_version(self):
+ """Get PCiE version from SONiC
+ :returns: version dict { "PCIE_FW_LOADER": "2.5", "PCIE_FW": "D102_08" }
+
+ """
+ cmd = "sudo bcmcmd 'pciephy fw version'"
+ p = subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ raw_data, err = p.communicate()
+
+ pcie_version = dict()
+ pcie_version["PCIE_FW_LOADER"] = 'None'
+ pcie_version["PCIE_FW"] = 'None'
+
+ if err == '':
+ lines = raw_data.split('\n')
+ for line in lines:
+ if 'PCIe FW loader' in line:
+ pcie_version["PCIE_FW_LOADER"] = line.split(':')[1].strip()
+ elif 'PCIe FW version' in line:
+ pcie_version["PCIE_FW"] = line.split(':')[1].strip()
+ return pcie_version
+
+ def get_fpga_version(self):
+ """Get FPGA version from SONiC
+ :returns: version string
+
+ """
+ version = self.__get_register_value(self.fpga_version_path, '0x00')
+ if version is not 'None':
+ version = "{}.{}".format(
+ int(version[2:][:4], 16), int(version[2:][4:], 16))
+ return str(version)
+
+ def firmware_upgrade(self, fw_type, fw_path, fw_extra=None):
+ """
+ @fw_type MANDATORY, firmware type, should be one of the strings: 'cpld', 'fpga', 'bios', 'bmc'
+ @fw_path MANDATORY, target firmware file
+ @fw_extra OPTIONAL, extra information string,
+
+ for fw_type 'cpld' and 'fpga': it can be used to indicate specific cpld, such as 'cpld1', 'cpld2', ...
+ or 'cpld_fan_come_board', etc. If None, upgrade all CPLD/FPGA firmware. for fw_type 'bios' and 'bmc',
+ value should be one of 'master' or 'slave' or 'both'
+ """
+ fw_type = fw_type.lower()
+ bmc_pwd = self.get_bmc_pass()
+ if not bmc_pwd and fw_type != "fpga":
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=BMC credential not found")
+ return False
+
+ if fw_type == 'bmc':
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "start BMC upgrade")
+ # Copy BMC image file to BMC
+ fw_extra_str = str(fw_extra).lower()
+ last_fw_upgrade = ["BMC", fw_path, fw_extra_str, "FAILED"]
+ upload_file = self.upload_file_bmc(fw_path)
+ if not upload_file:
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=unable to upload BMC image to BMC")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ filename_w_ext = os.path.basename(fw_path)
+ json_data = dict()
+ json_data["path"] = "root@127.0.0.1:/home/root/%s" % filename_w_ext
+ json_data["password"] = bmc_pwd
+
+ # Set flash type
+ current_bmc = self.get_running_bmc()
+ flash = fw_extra_str if fw_extra_str in [
+ "master", "slave", "both"] else "both"
+ if fw_extra_str == "pingpong":
+ #flash = "master" if current_bmc == "slave" else "slave"
+ flash = "slave"
+ json_data["flash"] = flash
+
+ # Install BMC
+ if flash == "both":
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "install BMC as master mode")
+ json_data["flash"] = "master"
+ r = requests.post(self.bmc_info_url, json=json_data)
+ if r.status_code != 200 or 'success' not in r.json().get('result'):
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "fail, message=BMC API report error code %d" % r.status_code)
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+ json_data["flash"] = "slave"
+
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "install BMC as %s mode" % json_data["flash"])
+ r = requests.post(self.bmc_info_url, json=json_data)
+ if r.status_code == 200 and 'success' in r.json().get('result'):
+ if fw_extra_str == "pingpong":
+ flash = "master" if current_bmc == "slave" else "slave"
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "switch to boot from %s" % flash)
+ self.set_bmc_boot_flash(flash)
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "reboot BMC")
+ if not self.reboot_bmc():
+ return False
+ else:
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "reboot BMC")
+ reboot_dict = {}
+ reboot_dict["reboot"] = "yes"
+ r = requests.post(self.bmc_info_url, json=reboot_dict)
+ last_fw_upgrade[3] = "DONE"
+ else:
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "fail, message=unable to install BMC image")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "done")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return True
+
+ elif fw_type == 'fpga':
+ last_fw_upgrade = ["FPGA", fw_path, None, "FAILED"]
+ self.__update_fw_upgrade_logger(
+ "fpga_upgrade", "start FPGA upgrade")
+
+ if not os.path.isfile(fw_path):
+ self.__update_fw_upgrade_logger(
+ "fpga_upgrade", "fail, message=FPGA image not found %s" % fw_path)
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ command = 'fpga_prog ' + fw_path
+ print("Running command : %s" % command)
+ process = subprocess.Popen(
+ command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ while True:
+ output = process.stdout.readline()
+ if output == '' and process.poll() is not None:
+ break
+
+ rc = process.returncode
+ if rc != 0:
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=unable to install FPGA")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ self.__update_fw_upgrade_logger("fpga_upgrade", "done")
+ last_fw_upgrade[3] = "DONE"
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ self.firmware_refresh(["FPGA"], None, None)
+ return True
+
+ elif 'cpld' in fw_type:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "start CPLD upgrade")
+ # Check input
+ fw_extra_str = str(fw_extra).upper()
+ if ":" in fw_path and ":" in fw_extra_str:
+ fw_path_list = fw_path.split(":")
+ fw_extra_str_list = fw_extra_str.split(":")
+ else:
+ fw_path_list = [fw_path]
+ fw_extra_str_list = [fw_extra_str]
+
+ if len(fw_path_list) != len(fw_extra_str_list):
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=invalid input")
+ return False
+
+ data_list = list(zip(fw_path_list, fw_extra_str_list))
+ refresh_img_path = None
+ cpld_result_list = ["FAILED" for i in range(
+ 0, len(fw_extra_str_list))]
+ last_fw_upgrade = ["CPLD", ":".join(
+ fw_path_list), ":".join(fw_extra_str_list), ":".join(cpld_result_list)]
+ for i in range(0, len(data_list)):
+ data = data_list[i]
+ fw_path = data[0]
+ fw_extra_str = data[1]
+
+ # Set fw_extra
+ fw_extra_str = {
+ "TOP_LC_CPLD": "top_lc",
+ "BOT_LC_CPLD": "bottom_lc",
+ "FAN_CPLD": "fan",
+ "CPU_CPLD": "cpu",
+ "BASE_CPLD": "base",
+ "COMBO_CPLD": "combo",
+ "SW_CPLD1": "switch",
+ "SW_CPLD2": "switch",
+ "REFRESH_CPLD": "refresh"
+ }.get(fw_extra_str, None)
+
+ if fw_extra_str == "refresh":
+ refresh_img_path = fw_path
+ del cpld_result_list[i]
+ del fw_extra_str_list[i]
+ continue
+
+ if fw_extra_str is None:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=invalid extra information string")
+ continue
+
+ # Uploading image to BMC
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "start %s upgrade" % data[1])
+ upload_file = self.upload_file_bmc(fw_path)
+ if not upload_file:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=unable to upload BMC image to BMC")
+ continue
+
+ filename_w_ext = os.path.basename(fw_path)
+ json_data = dict()
+ json_data["image_path"] = "root@127.0.0.1:/home/root/%s" % filename_w_ext
+ json_data["password"] = bmc_pwd
+ json_data["device"] = "cpld"
+ json_data["reboot"] = "no"
+ json_data["type"] = fw_extra_str
+
+ # Call BMC api to install cpld image
+ print("Installing...")
+ r = requests.post(self.fw_upgrade_url, json=json_data)
+ if r.status_code != 200 or 'success' not in r.json().get('result'):
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=invalid cpld image")
+ continue
+
+ cpld_result_list[i] = "DONE"
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "%s upgrade done" % data[1])
+ last_fw_upgrade[3] = ":".join(cpld_result_list)
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "done")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+
+ # Refresh CPLD
+ refresh_img_str_list = []
+ for fw_extra in fw_extra_str_list:
+ if "BASE_CPLD" in fw_extra or "FAN_CPLD" in fw_extra:
+ refresh_img_str_list.append(refresh_img_path)
+ else:
+ refresh_img_str_list.append("None")
+ self.firmware_refresh(None, fw_extra_str_list,
+ ":".join(refresh_img_str_list))
+
+ return True
+
+ elif 'bios' in fw_type:
+ self.__update_fw_upgrade_logger(
+ "bios_upgrade", "start BIOS upgrade")
+ last_fw_upgrade = ["BIOS", fw_path, None, "FAILED"]
+ fw_extra_str = str(fw_extra).lower()
+ flash = fw_extra_str if fw_extra_str in [
+ "master", "slave"] else "master"
+
+ if not os.path.exists(fw_path):
+ self.__update_fw_upgrade_logger(
+ "bios_upgrade", "fail, message=image not found")
+ return False
+
+ scp_command = 'sudo scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -r %s root@240.1.1.1:/home/root/' % os.path.abspath(
+ fw_path)
+ child = pexpect.spawn(scp_command)
+ i = child.expect(["root@240.1.1.1's password:"], timeout=30)
+ if i != 0:
+ self.__update_fw_upgrade_logger(
+ "bios_upgrade", "fail, message=unable to upload image to BMC")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ child.sendline(bmc_pwd)
+ data = child.read()
+ print(data)
+ child.close
+
+ json_data = dict()
+ json_data["data"] = "/usr/bin/ipmitool -b 1 -t 0x2c raw 0x2e 0xdf 0x57 0x01 0x00 0x01"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ self.__update_fw_upgrade_logger(
+ "bios_upgrade", "fail, message=unable to set state")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ filename_w_ext = os.path.basename(fw_path)
+ json_data = dict()
+ json_data["image_path"] = "root@127.0.0.1:/home/root/%s" % filename_w_ext
+ json_data["password"] = bmc_pwd
+ json_data["device"] = "bios"
+ json_data["flash"] = flash
+ json_data["reboot"] = "no"
+
+ print("Installing...")
+ r = requests.post(self.fw_upgrade_url, json=json_data)
+ if r.status_code != 200 or 'success' not in r.json().get('result'):
+ self.__update_fw_upgrade_logger(
+ "bios_upgrade", "fail, message=unable install bios")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ last_fw_upgrade[3] = "DONE"
+ self.__update_fw_upgrade_logger(
+ "bios_upgrade", "done")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ else:
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=invalid firmware type")
+ return False
+
+ return True
+
+ def get_last_upgrade_result(self):
+ """
+ Get last firmware upgrade information, inlcudes:
+ 1) FwType: cpld/fpga/bios/bmc(passed by method 'firmware_upgrade'), string
+ 2) FwPath: path and file name of firmware(passed by method 'firmware_upgrade'), string
+ 3) FwExtra: designated string, econdings of this string is determined by vendor(passed by method 'firmware_program')
+ 4) Result: indicates whether the upgrade action is performed and success/failure status if performed. Values should be one of: "DONE"/"FAILED"/"NOT_PERFORMED".
+ list of object:
+ [
+ {
+ "FwType": "cpld",
+ "FwPath": "cpu_cpld.vme"
+ "FwExtra":"CPU_CPLD"
+ "Result": "DONE"
+ },
+ {
+ "FwType": "cpld",
+ "FwPath": "fan_cpld.vme"
+ "FwExtra": "FAN_CPLD"
+ "Result": "FAILED"
+ }
+ ]
+ """
+ last_update_list = []
+
+ if os.path.exists(self.fw_upgrade_logger_path):
+ with open(self.fw_upgrade_logger_path, 'r') as file:
+ lines = file.read().splitlines()
+
+ upgrade_txt = [i for i in reversed(
+ lines) if "last_upgrade_result" in i]
+ if len(upgrade_txt) > 0:
+ last_upgrade_txt = upgrade_txt[0].split(
+ "last_upgrade_result : ")
+ last_upgrade_list = ast.literal_eval(last_upgrade_txt[1])
+ for x in range(0, len(last_upgrade_list[1].split(":"))):
+ upgrade_dict = {}
+ upgrade_dict["FwType"] = last_upgrade_list[0].lower()
+ upgrade_dict["FwPath"] = last_upgrade_list[1].split(":")[x]
+ upgrade_dict["FwExtra"] = last_upgrade_list[2].split(":")[
+ x] if last_upgrade_list[2] else "None"
+ upgrade_dict["Result"] = last_upgrade_list[3].split(":")[x]
+ last_update_list.append(upgrade_dict)
+
+ return last_update_list
+
+ def firmware_program(self, fw_type, fw_path, fw_extra=None):
+ """
+ Program FPGA and/or CPLD firmware only, but do not refresh them
+
+ @param fw_type value can be: FPGA, CPLD
+ @param fw_path a string of firmware file path, seperated by ':', it should
+ match the sequence of param @fw_type
+ @param fw_extra a string of firmware subtype, i.e CPU_CPLD, BOARD_CPLD,
+ FAN_CPLD, LC_CPLD, etc. Subtypes are seperated by ':'
+ @return True when all required firmware is program succefully,
+ False otherwise.
+
+ Example:
+ self.firmware_program("CPLD", "/cpu_cpld.vme:/lc_cpld", \
+ "CPU_CPLD:LC_CPLD")
+ or
+ self.firmware_program("FPGA", "/fpga.bin")
+ """
+ fw_type = fw_type.lower()
+ bmc_pwd = self.get_bmc_pass()
+ if not bmc_pwd and fw_type != "fpga":
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=BMC credential not found")
+ return False
+
+ if fw_type == 'fpga':
+ last_fw_upgrade = ["FPGA", fw_path, None, "FAILED"]
+ self.__update_fw_upgrade_logger(
+ "fpga_upgrade", "start FPGA upgrade")
+
+ if not os.path.isfile(fw_path):
+ self.__update_fw_upgrade_logger(
+ "fpga_upgrade", "fail, message=FPGA image not found %s" % fw_path)
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ command = 'fpga_prog ' + fw_path
+ print("Running command: %s" % command)
+ process = subprocess.Popen(
+ command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ while True:
+ output = process.stdout.readline()
+ if output == '' and process.poll() is not None:
+ break
+
+ rc = process.returncode
+ if rc != 0:
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=Unable to install FPGA")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ self.__update_fw_upgrade_logger("fpga_upgrade", "done")
+ last_fw_upgrade[3] = "DONE"
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return True
+
+ elif 'cpld' in fw_type:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "start CPLD upgrade")
+
+ # Check input
+ fw_extra_str = str(fw_extra).upper()
+ if ":" in fw_path and ":" in fw_extra_str:
+ fw_path_list = fw_path.split(":")
+ fw_extra_str_list = fw_extra_str.split(":")
+ else:
+ fw_path_list = [fw_path]
+ fw_extra_str_list = [fw_extra_str]
+
+ if len(fw_path_list) != len(fw_extra_str_list):
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=Invalid input")
+ return False
+
+ cpld_result_list = []
+ data_list = list(zip(fw_path_list, fw_extra_str_list))
+ for data in data_list:
+ fw_path = data[0]
+ fw_extra_str = data[1]
+
+ # Set fw_extra
+ fw_extra_str = {
+ "TOP_LC_CPLD": "top_lc",
+ "BOT_LC_CPLD": "bottom_lc",
+ "FAN_CPLD": "fan",
+ "CPU_CPLD": "cpu",
+ "BASE_CPLD": "base",
+ "COMBO_CPLD": "combo",
+ "SW_CPLD1": "switch",
+ "SW_CPLD2": "switch"
+ }.get(fw_extra_str, None)
+
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "start %s upgrade" % data[1])
+ upgrade_result = "FAILED"
+ for x in range(1, 4):
+ # Set fw_extra
+ if x > 1:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=Retry to upgrade %s" % data[1])
+
+ elif fw_extra_str is None:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=Invalid extra information string %s" % data[1])
+ break
+ elif not os.path.isfile(os.path.abspath(fw_path)):
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=CPLD image not found %s" % fw_path)
+ break
+
+ # Install cpld image via ispvm tool
+ print("Installing...")
+ command = 'ispvm %s' % fw_path
+ if fw_extra_str in ["top_lc", "bottom_lc"]:
+ option = 1 if fw_extra_str == "top_lc" else 2
+ command = "ispvm -c %d %s" % (option,
+ os.path.abspath(fw_path))
+ print("Running command : %s" % command)
+ process = subprocess.Popen(
+ command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ while True:
+ output = process.stdout.readline()
+ if output == '' and process.poll() is not None:
+ break
+
+ rc = process.returncode
+ if rc != 0:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=Unable to install CPLD")
+ continue
+
+ upgrade_result = "DONE"
+ self.__update_fw_upgrade_logger("cpld_upgrade", "done")
+ break
+ cpld_result_list.append(upgrade_result)
+
+ last_fw_upgrade = ["CPLD", ":".join(
+ fw_path_list), ":".join(fw_extra_str_list), ":".join(cpld_result_list)]
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return "FAILED" not in cpld_result_list
+ else:
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=Invalid firmware type")
+ return False
+
+ return True
+
+ def firmware_refresh(self, fpga_list, cpld_list, fw_extra=None):
+ """
+ Refresh firmware and take extra action when necessary.
+ @param fpga_list a list of FPGA names
+ @param cpld_list a list of CPLD names
+ @return True if refresh succefully and no power cycle action is taken.
+
+ @Note extra action should be: power cycle the whole system(except BMC) when
+ CPU_CPLD or BOARD_CPLD or FPGA is refreshed.
+ No operation if the power cycle is not needed.
+
+ Example:
+ self.firmware_refresh(
+ ["FPGA"], ["BASE_CPLD", "LC_CPLD"],"/tmp/fw/refresh.vme")
+ or
+ self.firmware_refresh(["FPGA"], None, None)
+ or
+ self.firmware_refresh(None, ["FAN_CPLD", "LC1_CPLD", "BASE_CPLD"],
+ "/tmp/fw/fan_refresh.vme:none:/tmp/fw/base_refresh.vme")
+ """
+
+ if not fpga_list and not cpld_list:
+ return False
+
+ if type(cpld_list) is list and ("BASE_CPLD" in cpld_list or "FAN_CPLD" in cpld_list):
+ refresh_list = fpga_list + \
+ cpld_list if type(fpga_list) is list else cpld_list
+ self.__update_fw_upgrade_logger(
+ "fw_refresh", "start %s refresh" % ",".join(refresh_list))
+ fw_path_list = fw_extra.split(':')
+ command = "echo "
+ if len(fw_path_list) != len(cpld_list):
+ self.__update_fw_upgrade_logger(
+ "cpld_refresh", "fail, message=Invalid fw_extra")
+ return False
+
+ for idx in range(0, len(cpld_list)):
+ fw_path = fw_path_list[idx]
+ refresh_type = {
+ "BASE_CPLD": "base",
+ "FAN_CPLD": "fan"
+ }.get(cpld_list[idx], None)
+
+ if not refresh_type:
+ continue
+ elif not self.upload_file_bmc(fw_path):
+ self.__update_fw_upgrade_logger(
+ "cpld_refresh", "fail, message=Unable to upload refresh image to BMC")
+ return False
+ else:
+ filename_w_ext = os.path.basename(fw_path)
+
+ sub_command = "%s /home/root/%s > /tmp/cpld_refresh " % (
+ refresh_type, filename_w_ext)
+ command += sub_command
+
+ json_data = dict()
+ json_data["data"] = command
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ self.__update_fw_upgrade_logger(
+ "cpld_refresh", "fail, message=%d Invalid refresh image" % r.status_code)
+ return False
+ elif type(cpld_list) is list:
+ refresh_list = fpga_list + \
+ cpld_list if type(fpga_list) is list else cpld_list
+ self.__update_fw_upgrade_logger(
+ "fw_refresh", "start %s refresh" % ",".join(refresh_list))
+ json_data = dict()
+ json_data["data"] = "echo cpu_cpld > /tmp/cpld_refresh"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ self.__update_fw_upgrade_logger(
+ "cpld_refresh", "fail, message=%d Unable to load new CPLD" % r.status_code)
+ return False
+ elif type(fpga_list) is list:
+ self.__update_fw_upgrade_logger(
+ "fw_refresh", "start FPGA refresh")
+ json_data = dict()
+ json_data["data"] = "echo fpga > /tmp/cpld_refresh"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ self.__update_fw_upgrade_logger(
+ "cpld_refresh", "fail, message=%d Unable to load new FPGA" % r.status_code)
+ return False
+ else:
+ self.__update_fw_upgrade_logger(
+ "fw_refresh", "fail, message=Invalid input")
+ return False
+
+ self.__update_fw_upgrade_logger("fw_refresh", "done")
+ return True
+
+ def get_running_bmc(self):
+ """
+ Get booting flash of running BMC.
+ @return a string, "master" or "slave"
+ """
+ json_data = dict()
+ json_data["data"] = "/usr/local/bin/boot_info.sh"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ try:
+ boot_info_list = r.json().get('result')
+ for boot_info_raw in boot_info_list:
+ boot_info = boot_info_raw.split(":")
+ if "Current Boot Code Source" in boot_info[0]:
+ flash = "master" if "master "in boot_info[1].lower(
+ ) else "slave"
+ return flash
+ raise Exception(
+ "Error: Unable to detect booting flash of running BMC")
+ except Exception as e:
+ raise Exception(e)
+
+ def set_bmc_boot_flash(self, flash):
+ """
+ Set booting flash of BMC
+ @param flash should be "master" or "slave"
+ """
+ if flash.lower() not in ["master", "slave"]:
+ return False
+ json_data = dict()
+ json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;bmc_reboot %s" % flash
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ return False
+ return True
+
+ def reboot_bmc(self):
+ """
+ Reboot BMC
+ """
+ json_data = dict()
+ json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;bmc_reboot reboot"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ return False
+ return True
+
+ def get_current_bios(self):
+ """
+ # Get booting bios image of current running host OS
+ # @return a string, "master" or "slave"
+ """
+ json_data = dict()
+ json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;come_boot_info"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ try:
+ cpu_boot_info_list = r.json().get('result')
+ for cpu_boot_info_raw in cpu_boot_info_list:
+ if "COMe CPU boots from BIOS" in cpu_boot_info_raw:
+ bios_image = "master" if "master "in cpu_boot_info_raw.lower(
+ ) else "slave"
+ return bios_image
+ raise Exception(
+ "Error: Unable to detect current running bios image")
+ except Exception as e:
+ raise Exception(e)
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/optictemputil.py b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/optictemputil.py
new file mode 100644
index 000000000000..0e5b6a1c7109
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/optictemputil.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+
+#
+# optictemputil.py
+#
+# Platform-specific Optic module temperature Interface for SONiC
+#
+
+__author__ = 'Pradchaya P.'
+__author__ = 'Wirut G.'
+__license__ = "GPL"
+__version__ = "1.0.0"
+__status__ = "Development"
+
+import os
+import sys
+import binascii
+import subprocess
+
+class OpticTempUtil():
+ """Platform-specific OpticTempUtil class"""
+
+ def __init__(self):
+ pass
+
+ def read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes):
+ eeprom_raw = []
+ for i in range(0, num_bytes):
+ eeprom_raw.append("0x00")
+
+ try:
+ sysfsfile_eeprom.seek(offset)
+ raw = sysfsfile_eeprom.read(num_bytes)
+ except IOError:
+ return None
+
+ try:
+ for n in range(0, num_bytes):
+ eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
+ except:
+ return None
+
+ return eeprom_raw
+
+
+ def twos_comp(self, num, bits):
+ try:
+ if ((num & (1 << (bits - 1))) != 0):
+ num = num - (1 << bits)
+ return num
+ except:
+ return 0
+
+
+ def calc_temperature(self, cal_type, eeprom_data, offset, size):
+
+ msb = int(eeprom_data[offset], 16)
+ lsb = int(eeprom_data[offset + 1], 16)
+
+ result = (msb << 8) | (lsb & 0xff)
+ result = self.twos_comp(result, 16)
+
+ if cal_type == 1:
+ # Internal calibration
+ result = float(result / 256.0)
+ retval = '%.4f' %result
+
+ # TODO: Should support external calibration in future.
+ else:
+ retval = 0
+
+ return retval
+
+ ''' TODO: Change busnum to sysfs_sfp_i2c_client_eeprom_path from caller!!!
+ '''
+ def get_optic_temp(self, sysfs_sfp_i2c_client_eeprom_path, port_type):
+
+ EEPROM_ADDR = 0x50
+ DOM_ADDR = 0x51
+ EEPROM_OFFSET = 0
+ DOM_OFFSET = 256
+
+ SFP_DMT_ADDR = 92
+ SFP_DMT_WIDTH = 1
+ SFP_TEMP_DATA_ADDR = 96
+ SFP_TEMP_DATA_WIDTH = 2
+
+ QSFP_TEMP_DATA_ADDR = 22
+ QSFP_TEMP_DATA_WIDTH = 2
+ temperature_raw = None
+
+
+ ''' Open file here '''
+ try:
+ sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0)
+ except IOError:
+ print("Error: reading sysfs file %s" % sysfs_sfp_i2c_client_eeprom_path)
+ return 0
+
+ if port_type == 'QSFP':
+
+ # QSFP only have internal calibration mode.
+ cal_type = 1
+ # read temperature raw value
+ temperature_raw = self.read_eeprom_specific_bytes(sysfsfile_eeprom,(EEPROM_OFFSET+QSFP_TEMP_DATA_ADDR),QSFP_TEMP_DATA_WIDTH)
+ else:
+ # read calibration type at bit 5
+ cal_type = self.read_eeprom_specific_bytes(sysfsfile_eeprom,EEPROM_OFFSET+SFP_DMT_ADDR,SFP_DMT_WIDTH)
+ if cal_type is None:
+ return 0
+ else:
+ cal_type = (int(cal_type[0],16) >> 5 ) & 1
+ # read temperature raw value
+ temperature_raw = self.read_eeprom_specific_bytes(sysfsfile_eeprom,(DOM_OFFSET+SFP_TEMP_DATA_ADDR),SFP_TEMP_DATA_WIDTH)
+
+ try:
+ sysfsfile_eeprom.close()
+ except IOError:
+ print("Error: closing sysfs file %s" % file_path)
+ return 0
+
+ #calculate temperature
+ if temperature_raw is not None:
+ return self.calc_temperature(cal_type, temperature_raw, 0, 2)
+ else:
+ return 0
\ No newline at end of file
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/psuutil.py b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/psuutil.py
new file mode 100644
index 000000000000..55c3a41e1f68
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/psuutil.py
@@ -0,0 +1,248 @@
+#!/usr/bin/env python
+
+__author__ = 'Wirut G.'
+__license__ = "GPL"
+__version__ = "0.1.4"
+__status__ = "Development"
+
+import requests
+import re
+
+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.fru_status_url = "http://240.1.1.1:8080/api/sys/fruid/status"
+ self.psu_info_url = "http://240.1.1.1:8080/api/sys/fruid/psu"
+
+ self.fru_status_list = None
+ self.psu_info_list = None
+
+ def request_data(self):
+ # Reqest data from BMC if not exist.
+ if self.fru_status_list is None or self.psu_info_list is None:
+ fru_status_req = requests.get(self.fru_status_url)
+ psu_info_req = requests.get(self.psu_info_url)
+ fru_status_json = fru_status_req.json()
+ psu_info_json = psu_info_req.json()
+ self.fru_status_list = fru_status_json.get('Information')
+ self.psu_info_list = psu_info_json.get('Information')
+ return self.fru_status_list, self.psu_info_list
+
+ def airflow_selector(self, pn):
+ # Set airflow type
+ pn = pn.upper()
+ if "DPS-1100FB" in pn:
+ airflow = "FTOB"
+ elif "DPS-1100AB" in pn:
+ airflow = "BTOF"
+ elif "FSJ026-A20G" in pn:
+ airflow = "FTOB"
+ elif "FSJ038-A20G" in pn:
+ airflow = "BTOF"
+ else:
+ airflow = "Unknown"
+ return airflow
+
+ 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
+ """
+
+ num_psus = 4
+
+ return num_psus
+
+ 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
+ """
+
+ # init data
+ psu_key = "PSU" + str(index)
+ psu_status_key = "Power Status"
+ psu_power_status = False
+
+ try:
+ # Request and validate sensor's information
+ self.fru_status_list, self.psu_info_list = self.request_data()
+
+ # Get PSU power status.
+ for fru_status in self.fru_status_list:
+ is_psu = fru_status.get(psu_key)
+ psu_status = str(fru_status.get(psu_status_key)).strip()
+
+ if is_psu is not None and psu_status == "OK":
+ psu_power_status = True
+
+ except:
+ print("Error: Unable to access PSU power status")
+ return False
+
+ return psu_power_status
+
+ 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
+ """
+
+ # Init data
+ psu_key = "PSU" + str(index)
+ psu_presence_key = "Present"
+ psu_presence_status = False
+
+ try:
+ # Request and validate sensor's information.
+ self.fru_status_list, self.psu_info_list = self.request_data()
+
+ # Get PSU present status.
+ for fru_status in self.fru_status_list:
+ is_psu = fru_status.get(psu_key)
+ psu_status = str(fru_status.get(psu_presence_key)).strip()
+
+ if is_psu is not None and psu_status == "Present":
+ psu_presence_status = True
+
+ except:
+ print("Error: Unable to access PSU presence status")
+ return False
+
+ return psu_presence_status
+
+ def get_psu_sn(self, index):
+ """
+ Get the serial number of the psu,
+
+ :param index: An integer, 1-based index of the PSU.
+ :return: Serial number
+ """
+ serial_number = "N/A"
+ psu_key = "PSU" + str(index) + " FRU"
+ psu_sn_key = "Serial Number"
+
+ try:
+ # Request and validate sensor's information.
+ self.fru_status_list, self.psu_info_list = self.request_data()
+
+ # Get PSU fru info.
+ for psu_fru in self.psu_info_list:
+ psu_sn = str(psu_fru.get(psu_sn_key)).strip()
+ if psu_fru.get(psu_key) is not None:
+ serial_number = psu_sn if psu_sn.strip() != "" else "N/A"
+ break
+
+ except:
+ return "N/A"
+
+ return serial_number
+
+ def get_psu_pn(self, index):
+ """
+ Get the product name of the psu
+
+ :param index: An integer, 1-based index of the PSU.
+ :return: Product name
+ """
+ product_name = "N/A"
+ psu_key = "PSU" + str(index) + " FRU"
+ psu_pn_key = "Product Name"
+
+ try:
+ # Request and validate sensor's information
+ self.fru_status_list, self.psu_info_list = self.request_data()
+
+ # Get PSU fru info.
+ for psu_fru in self.psu_info_list:
+ psu_pn = str(psu_fru.get(psu_pn_key)).strip()
+ if psu_fru.get(psu_key) is not None:
+ product_name = psu_pn if psu_pn.strip() != "" else "N/A"
+ break
+
+ except:
+ return "N/A"
+
+ return product_name
+
+ def get_all(self):
+ """
+ Number: mandatory, max number of PSU, integer
+ PSU1, PSU2, ...: mandatory, PSU name, string
+ Present: mandatory for each PSU, present status, boolean, True for present, False for NOT present
+ PowerStatus: conditional, if PRESENT is True, power status of PSU,boolean, True for powered, False for NOT powered
+ PN, conditional, if PRESENT is True, PN of the PSU, string
+ SN, conditional, if PRESENT is True, SN of the PSU, string
+ """
+
+ # Init data
+ all_psu_dict = dict()
+ all_psu_dict["Number"] = self.get_num_psus()
+ psu_sn_key_1 = "Serial Number"
+ psu_sn_key_2 = "Product Serial"
+ psu_pn_key = "Product Name"
+
+ # Request and validate sensor's information.
+ self.fru_status_list, self.psu_info_list = self.request_data()
+
+ # Set PSU FRU data.
+ psu_info_dict = dict()
+ for psu_fru in self.psu_info_list:
+ psu_data = dict()
+ pn = psu_fru.get(psu_pn_key)
+ sn = psu_fru.get(psu_sn_key_1) or psu_fru.get(psu_sn_key_2)
+ psu_data["PN"] = "N/A" if not pn or str(
+ pn).strip() == "" else str(pn).strip()
+ psu_data["SN"] = "N/A" if not pn or str(
+ pn).strip() == "" else str(sn).strip()
+
+ fru_check = [psu_fru[v] for v in psu_fru.keys() if 'FRU Info' in v]
+ non_fru_check = [v for v in psu_fru.keys() if 'PSU' in v]
+
+ if len(non_fru_check) > 0:
+ psu_idx = int(re.findall('\d+', non_fru_check[0])[0])
+ psu_info_dict[psu_idx] = psu_data
+ elif len(fru_check) > 0:
+ psu_idx = int(re.findall('\d+', fru_check[0])[0])
+ psu_info_dict[psu_idx] = psu_data
+
+ # Set PSU status.
+ for fru_status in self.fru_status_list:
+ psu_status_dict = dict()
+ find_psu = [v for v in fru_status.keys() if "PSU" in v]
+ if len(find_psu) > 0:
+ psu_idx = int(re.findall('\d+', find_psu[0])[0])
+ psu_ps_status = True if str(fru_status.get(
+ "Present")).strip() == "Present" else False
+ psu_pw_status = True if str(fru_status.get(
+ "Power Status")).strip() == "OK" else False
+ psu_pw_type = str(fru_status.get(
+ "Power Type")).strip()
+ ac_status = True if str(fru_status.get(
+ "AC Status")).strip().upper() == "OK" else False
+
+ psu_status_dict["Present"] = psu_ps_status
+ if psu_ps_status:
+ psu_status_dict["PowerStatus"] = psu_pw_status
+ psu_status_dict["PN"] = psu_info_dict[psu_idx]["PN"]
+ psu_status_dict["SN"] = psu_info_dict[psu_idx]["SN"]
+ psu_status_dict["InputType"] = psu_pw_type
+ psu_status_dict["InputStatus"] = True if psu_pw_status and psu_ps_status else False
+ psu_status_dict["OutputStatus"] = ac_status
+ psu_status_dict["AirFlow"] = self.airflow_selector(
+ psu_status_dict["PN"])
+ all_psu_dict[find_psu[0]] = psu_status_dict
+
+ return all_psu_dict
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/sensorutil.py b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/sensorutil.py
new file mode 100644
index 000000000000..29f56e8578e6
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/sensorutil.py
@@ -0,0 +1,383 @@
+#!/usr/bin/env python
+
+__author__ = 'Wirut G.'
+__license__ = "GPL"
+__version__ = "0.2.0"
+__status__ = "Development"
+
+import requests
+
+
+class SensorUtil():
+ """Platform-specific SensorUtil class"""
+
+ def __init__(self):
+ self.sensor_url = "http://240.1.1.1:8080/api/sys/sensors"
+ self.sys_fruid_url = "http://240.1.1.1:8080/api/sys/fruid/sys"
+ self.sensor_info_list = None
+
+ def request_data(self):
+ # Reqest data from BMC if not exist.
+ if self.sensor_info_list is None:
+ sensor_data_req = requests.get(self.sensor_url)
+ sensor_json = sensor_data_req.json()
+ self.sensor_info_list = sensor_json.get('Information')
+ sys_fruid_req = requests.get(self.sys_fruid_url)
+ sys_fruid_json = sys_fruid_req.json()
+ self.sys_fruid_list = sys_fruid_json.get('Information')
+ return self.sensor_info_list
+
+ def input_type_selector(self, unit):
+ # Set input type.
+ return {
+ "C": "temperature",
+ "V": "voltage",
+ "RPM": "RPM",
+ "A": "amp",
+ "W": "power"
+ }.get(unit, unit)
+
+ def input_name_selector(self, sensor_name, input_name):
+
+ self.sensor_name = {
+ "syscpld-i2c-0-0d": "TEMPERATURE",
+ "dps1100-i2c-27-58": "PSU1",
+ "dps1100-i2c-26-58": "PSU2",
+ "dps1100-i2c-25-58": "PSU3",
+ "dps1100-i2c-24-58": "PSU4",
+ "fancpld-i2c-8-0d": "FAN",
+ "isl68137-i2c-17-60": "ISL68137"
+ }.get(sensor_name, sensor_name)
+
+ if 'dps1100' in sensor_name:
+ input_name = {
+ "fan1": self.sensor_name + "_FAN",
+ "iin": self.sensor_name + "_CURR_I",
+ "iout1": self.sensor_name + "_CURR_O",
+ "pin": self.sensor_name + "_POWER_I",
+ "pout1": self.sensor_name + "_POWER_O",
+ "temp1": self.sensor_name + "_TEMP1",
+ "temp2": self.sensor_name + "_TEMP2",
+ "vin": self.sensor_name + "_VOL_I",
+ "vout1": self.sensor_name + "_VOL_O"
+ }.get(input_name, input_name)
+
+ elif 'isl68137' in sensor_name:
+ input_name = {
+ "iin": self.sensor_name + "_CURR_I",
+ "iout2": self.sensor_name + "_CURR_O",
+ "pin": self.sensor_name + "_POWER_I",
+ "pout2": self.sensor_name + "_POWER_O",
+ "vin": self.sensor_name + "_VOL_I",
+ "vout2": self.sensor_name + "_VOL_O",
+ "temp1": self.sensor_name + "_TEMP1"
+ }.get(input_name, input_name)
+
+ elif 'tmp75' in sensor_name or 'max31730' in sensor_name:
+ input_name = {
+ "tmp75-i2c-7-4f": "BASEBOARD_INLET_RIGHT",
+ "tmp75-i2c-7-4e": "BASEBOARD_INLET_CENTER",
+ "tmp75-i2c-7-4d": "SWITCH_OUTLET",
+ "tmp75-i2c-31-48": "PSU_INLET_LEFT",
+ "tmp75-i2c-31-49": "INLET_TEMP",
+ "tmp75-i2c-39-48": "FANBOARD_LEFT",
+ "tmp75-i2c-39-49": "FANBOARD_RIGHT",
+ "tmp75-i2c-42-48": "LINECARD_TOP_RIGHT",
+ "tmp75-i2c-42-49": "LINECARD_TOP_LEFT",
+ "tmp75-i2c-43-48": "LINECARD_BOTTOM_RIGHT",
+ "tmp75-i2c-43-49": "LINECARD_BOTTOM_LEFT",
+ "max31730-i2c-7-4c": "SWITCH_REMOTE_" + input_name
+ }.get(sensor_name, input_name)
+ self.sensor_name = "TEMPERATURE"
+
+ elif 'fancpld' in sensor_name:
+ raw_fan_input = input_name.split()
+ input_name = raw_fan_input[0] + \
+ raw_fan_input[1] + "_" + raw_fan_input[2]
+
+ elif 'ir35' in sensor_name or 'ir38' in sensor_name:
+ sensor_name_raw = sensor_name.split("-")
+ sensor_name = sensor_name_raw[0]
+ self.sensor_name = sensor_name.upper()
+
+ return input_name.replace(" ", "_").upper()
+
+ def get_num_sensors(self):
+ """
+ Get the number of sensors
+ :return: int num_sensors
+ """
+
+ num_sensors = 0
+ try:
+ # Request and validate sensor's information
+ self.sensor_info_list = self.request_data()
+
+ # Get number of sensors.
+ num_sensors = len(self.sensor_info_list)
+ except:
+ print "Error: Unable to access sensor information"
+ return 0
+
+ return num_sensors
+
+ def get_sensor_input_num(self, index):
+ """
+ Get the number of the input items of the specified sensor
+ :return: int input_num
+ """
+
+ input_num = 0
+ try:
+ # Request and validate sensor's information.
+ self.sensor_info_list = self.request_data()
+
+ # Get sensor's input number.
+ sensor_data = self.sensor_info_list[index-1]
+ input_num = len(sensor_data.keys())-2
+ except:
+ print "Error: Unable to access sensor information"
+ return 0
+
+ return input_num
+
+ def get_sensor_name(self, index):
+ """
+ Get the device name of the specified sensor.
+ for example "coretemp-isa-0000"
+ :return: str sensor_name
+ """
+
+ sensor_name = "N/A"
+ try:
+ # Request and validate sensor's information.
+ self.sensor_info_list = self.request_data()
+
+ # Get sensor's name.
+ sensor_data = self.sensor_info_list[index-1]
+ sensor_name = sensor_data.get('name')
+
+ except:
+ return "N/A"
+
+ return sensor_name
+
+ def get_sensor_input_name(self, sensor_index, input_index):
+ """
+ Get the input item name of the specified input item of the
+ specified sensor index, for example "Physical id 0"
+ :return: str sensor_input_name
+ """
+
+ sensor_input_name = "N/A"
+ try:
+ # Request and validate sensor's information.
+ self.sensor_info_list = self.request_data()
+ sensor_data = self.sensor_info_list[sensor_index-1].copy()
+
+ # Remove none input key.
+ del sensor_data["name"]
+ del sensor_data["Adapter"]
+
+ # Get sensor's input name.
+ sensor_data_key = sensor_data.keys()
+ sensor_input_name = sensor_data_key[input_index-1]
+ except:
+ return "N/A"
+
+ return sensor_input_name
+
+ def get_sensor_input_type(self, sensor_index, input_index):
+ """
+ Get the item type of the specified input item of the specified sensor index,
+ The return value should among "valtage","temperature"
+ :return: str sensor_input_type
+ """
+
+ sensor_input_type = "N/A"
+ try:
+ # Request and validate sensor's information.
+ self.sensor_info_list = self.request_data()
+ sensor_data = self.sensor_info_list[sensor_index-1].copy()
+
+ # Remove none input key.
+ del sensor_data["name"]
+ del sensor_data["Adapter"]
+
+ # Get sensor's input type name.
+ sensor_data_key = sensor_data.keys()
+ sensor_input_raw = sensor_data.get(sensor_data_key[input_index-1])
+ sensor_data_str = sensor_input_raw.split()
+ sensor_input_type = self.input_type_selector(sensor_data_str[1])
+ except:
+ return "N/A"
+
+ return sensor_input_type
+
+ def get_sensor_input_value(self, sensor_index, input_index):
+ """
+ Get the current value of the input item, the unit is "V" or "C"
+ :return: float sensor_input_value
+ """
+
+ sensor_input_value = 0
+ try:
+ # Request and validate sensor's information.
+ self.sensor_info_list = self.request_data()
+ sensor_data = self.sensor_info_list[sensor_index-1].copy()
+
+ # Remove none input key.
+ del sensor_data["name"]
+ del sensor_data["Adapter"]
+
+ # Get sensor's input value.
+ sensor_data_key = sensor_data.keys()
+ sensor_input_raw = sensor_data.get(sensor_data_key[input_index-1])
+ sensor_data_str = sensor_input_raw.split()
+ sensor_input_value = float(
+ sensor_data_str[0]) if sensor_data_str[0] != "N/A" else 0
+ except:
+ print "Error: Unable to access sensor information"
+ return 0
+
+ return sensor_input_value
+
+ def get_sensor_input_low_threshold(self, sensor_index, input_index):
+ """
+ Get the low threshold of the value,
+ the status of this item is not ok if the current value 1:
+ sensor_input_low_threshold = l_thres * \
+ 1000 if str(unit[0]).lower() == 'k' else l_thres
+ except:
+ print "Error: Unable to access sensor information"
+ return 0
+
+ return sensor_input_low_threshold
+
+ def get_sensor_input_high_threshold(self, sensor_index, input_index):
+ """
+ Get the high threshold of the value,
+ the status of this item is not ok if the current value > high_threshold
+ :return: float sensor_input_high_threshold
+ """
+
+ sensor_input_high_threshold = 0
+ try:
+ # Request and validate sensor's information.
+ self.sensor_info_list = self.request_data()
+ sensor_data = self.sensor_info_list[sensor_index-1].copy()
+
+ # Remove none input key.
+ del sensor_data["name"]
+ del sensor_data["Adapter"]
+
+ # Get sensor's input high threshold.
+ sensor_data_key = sensor_data.keys()
+ sensor_input_raw = sensor_data.get(sensor_data_key[input_index-1])
+ sensor_data_str = sensor_input_raw.split()
+ indices = [i for i, s in enumerate(
+ sensor_data_str) if 'max' in s or 'high' in s]
+ h_thres = float(
+ sensor_data_str[indices[0] + 2]) if len(indices) != 0 else 0
+ unit = sensor_data_str[indices[0] +
+ 3] if len(indices) != 0 else None
+ if unit is not None and len(unit) > 1:
+ sensor_input_high_threshold = h_thres * \
+ 1000 if str(unit[0]).lower() == 'k' else h_thres
+
+ except:
+ print "Error: Unable to access sensor information"
+ return 0
+
+ return sensor_input_high_threshold
+
+ def get_sys_airflow(self):
+ sys_air_flow = "Unknown"
+ sys_pn_data = [
+ v.split(":") for v in self.sys_fruid_list if "Product Part Number" in v]
+
+ if len(sys_pn_data) == 0:
+ return sys_air_flow
+
+ sys_pn = sys_pn_data[0][1]
+ if "R1240-F0001" in sys_pn:
+ sys_air_flow = "FTOB"
+ elif"R1240-F0002" in sys_pn:
+ sys_air_flow = "BTOF"
+
+ return sys_air_flow
+
+ def get_all(self):
+
+ all_sensor_dict = dict()
+
+ # Request sensor's information.
+ self.sensor_info_list = self.request_data()
+ for sensor_data in self.sensor_info_list:
+ sensor_info = sensor_data.copy()
+
+ # Remove none unuse key.
+ del sensor_info["name"]
+ del sensor_info["Adapter"]
+
+ # Set sensor data.
+ sensor_dict = dict()
+ for k, v in sensor_info.items():
+ sensor_i_dict = dict()
+ sensor_data_str = v.split()
+ indices_h = [i for i, s in enumerate(
+ sensor_data_str) if 'max' in s or 'high' in s]
+ indices_l = [i for i, s in enumerate(
+ sensor_data_str) if 'min' in s or 'low' in s]
+ h_thres = float(
+ sensor_data_str[indices_h[0] + 2]) if len(indices_h) != 0 else 0
+ l_thres = float(
+ sensor_data_str[indices_l[0] + 2]) if len(indices_l) != 0 else 0
+ thres_unit = sensor_data_str[-1]
+
+ sensor_i_dict["Type"] = self.input_type_selector(
+ sensor_data_str[1])
+ sensor_i_dict["Value"] = float(
+ sensor_data_str[0]) if sensor_data_str[0] != "N/A" else 0
+ sensor_i_dict["HighThd"] = h_thres * \
+ 1000 if str(thres_unit[0]).lower() == 'k' else h_thres
+ sensor_i_dict["LowThd"] = l_thres * \
+ 1000 if str(thres_unit[0]).lower() == 'k' else l_thres
+
+ k = self.input_name_selector(sensor_data.get('name'), k)
+ sensor_dict[k] = sensor_i_dict
+
+ if all_sensor_dict.get(self.sensor_name) is None:
+ all_sensor_dict[self.sensor_name] = dict()
+
+ all_sensor_dict[self.sensor_name].update(sensor_dict)
+
+ sensor_dict = dict()
+ sensor_dict["Sys_AirFlow"] = self.get_sys_airflow()
+ all_sensor_dict["TEMPERATURE"].update(sensor_dict)
+
+ return all_sensor_dict
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/sfputil.py b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/sfputil.py
new file mode 100755
index 000000000000..2831a75af545
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/plugins/sfputil.py
@@ -0,0 +1,205 @@
+#!/usr/bin/env python
+#
+# Platform-specific SFP transceiver interface for SONiC
+#
+
+try:
+ import time
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
+
+
+class SfpUtil(SfpUtilBase):
+ """Platform-specific SfpUtil class"""
+
+ PORT_START = 1
+ PORT_END = 128
+ QSFP_PORT_START = 1
+ QSFP_PORT_END = 128
+
+ EEPROM_OFFSET = 9
+ PORT_INFO_PATH = '/sys/class/phalanx_fpga'
+
+ _port_name = ""
+ _port_to_eeprom_mapping = {}
+ _port_to_i2cbus_mapping = {}
+
+ @property
+ def port_start(self):
+ return self.PORT_START
+
+ @property
+ def port_end(self):
+ return self.PORT_END
+
+ @property
+ def qsfp_ports(self):
+ return range(self.QSFP_PORT_START, self.QSFP_PORT_END + 1)
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+ @property
+ def port_to_i2cbus_mapping(self):
+ return self._port_to_i2cbus_mapping
+
+ def get_port_name(self, port_num):
+ if port_num in self.qsfp_ports:
+ self._port_name = "QSFP" + str(port_num - self.QSFP_PORT_START + 1)
+ else:
+ self._port_name = "SFP" + str(port_num)
+ return self._port_name
+
+ def get_eeprom_dom_raw(self, port_num):
+ if port_num in self.qsfp_ports:
+ # QSFP DOM EEPROM is also at addr 0x50 and thus also stored in eeprom_ifraw
+ return None
+ else:
+ # Read dom eeprom at addr 0x51
+ return self._read_eeprom_devid(port_num, self.DOM_EEPROM_ADDR, 256)
+
+ def __init__(self):
+ # Override port_to_eeprom_mapping for class initialization
+ eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'
+
+ for x in range(self.PORT_START, self.PORT_END+1):
+ self.port_to_i2cbus_mapping[x] = (x + self.EEPROM_OFFSET)
+ self.port_to_eeprom_mapping[x] = eeprom_path.format(
+ x + self.EEPROM_OFFSET)
+ SfpUtilBase.__init__(self)
+
+ def get_presence(self, port_num):
+
+ # Check for invalid port_num
+ if port_num not in range(self.port_start, self.port_end + 1):
+ return False
+
+ # Get path for access port presence status
+ port_name = self.get_port_name(port_num)
+ sysfs_filename = "qsfp_modprs" if port_num in self.qsfp_ports else "sfp_modabs"
+ reg_path = "/".join([self.PORT_INFO_PATH, port_name, sysfs_filename])
+
+ # Read status
+ try:
+ reg_file = open(reg_path)
+ content = reg_file.readline().rstrip()
+ reg_value = int(content)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ # Module present is active low
+ if reg_value == 0:
+ return True
+
+ return False
+
+ def get_low_power_mode(self, port_num):
+ return NotImplementedError
+
+ def set_low_power_mode(self, port_num, lpmode):
+ # Check for invalid QSFP port_num
+ if port_num not in self.qsfp_ports:
+ return False
+
+ try:
+ port_name = self.get_port_name(port_num)
+ reg_file = open(
+ "/".join([self.PORT_INFO_PATH, port_name, "qsfp_lpmode"]), "r+")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = hex(lpmode)
+
+ reg_file.seek(0)
+ reg_file.write(content)
+ reg_file.close()
+
+ return True
+
+ def reset(self, port_num):
+ # Check for invalid QSFP port_num
+ if port_num not in self.qsfp_ports:
+ return False
+
+ try:
+ port_name = self.get_port_name(port_num)
+ reg_file = open(
+ "/".join([self.PORT_INFO_PATH, port_name, "qsfp_reset"]), "w")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ # Convert our register value back to a hex string and write back
+ reg_file.seek(0)
+ reg_file.write(hex(0))
+ reg_file.close()
+
+ # Sleep 1 second to allow it to settle
+ time.sleep(1)
+
+ # Flip the bit back high and write back to the register to take port out of reset
+ try:
+ reg_file = open(
+ "/".join([self.PORT_INFO_PATH, port_name, "qsfp_reset"]), "w")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_file.seek(0)
+ reg_file.write(hex(1))
+ reg_file.close()
+
+ return True
+
+ def get_transceiver_change_event(self, timeout=0):
+ """
+ TBD
+ """
+ return NotImplementedError
+
+ def tx_disable(self, port_num, disable):
+ """
+ @param port_num index of physical port
+ @param disable, True -- disable port tx signal
+ False -- enable port tx signal
+ @return True when operation success, False on failure.
+ """
+ TX_DISABLE_BYTE_OFFSET = 86
+ if port_num not in range(self.port_start, self.port_end + 1) or type(disable) != bool:
+ return False
+
+ # QSFP, set eeprom to disable tx
+ if port_num in self.qsfp_ports:
+ presence = self.get_presence(port_num)
+ if not presence:
+ return True
+
+ disable = b'\x0f' if disable else b'\x00'
+ # open eeprom
+ try:
+ with open(self.port_to_eeprom_mapping[port_num], mode="wb", buffering=0) as sysfsfile:
+ sysfsfile.seek(TX_DISABLE_BYTE_OFFSET)
+ sysfsfile.write(bytearray(disable))
+ except IOError:
+ return False
+ except:
+ return False
+
+ # SFP, set tx_disable pin
+ else:
+ try:
+ disable = hex(1) if disable else hex(0)
+ port_name = self.get_port_name(port_num)
+ reg_file = open(
+ "/".join([self.PORT_INFO_PATH, port_name, "sfp_txdisable"]), "w")
+ reg_file.write(disable)
+ reg_file.close()
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ return True
diff --git a/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/th3-as14-128h.config.bcm b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/th3-as14-128h.config.bcm
new file mode 100644
index 000000000000..354e0f2fad00
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-128h-cl-r0/th3-as14-128h.config.bcm
@@ -0,0 +1,631 @@
+pbmp_xport_xe.0=0x0ffff0ffff0ffff0ffff0ffff0ffff0ffff1fffe
+ccm_dma_enable=0
+ccmdma_intr_enable=0
+ctr_evict_enable=0
+mem_cache_enable=0
+parity_correction=0
+parity_enable=0
+phy_enable=0
+phy_null=1
+pll_bypass=1
+port_fec=3
+serdes_tx_taps_ce=pam4:0:140:0:0:0:0
+
+init_all_modules=0
+mdio_output_delay=64
+
+#BC1
+portmap_5=9:100:2
+portmap_6=11:100:2
+portmap_7=13:100:2
+portmap_8=15:100:2
+
+dport_map_port_5=1
+dport_map_port_6=2
+dport_map_port_7=4
+dport_map_port_8=3
+
+#BC9
+portmap_44=73:100:2
+portmap_45=75:100:2
+portmap_46=77:100:2
+portmap_47=79:100:2
+
+dport_map_port_44=8
+dport_map_port_45=7
+dport_map_port_46=5
+dport_map_port_47=6
+
+#BC0
+portmap_1=1:100:2
+portmap_2=3:100:2
+portmap_3=5:100:2
+portmap_4=7:100:2
+
+dport_map_port_1=9
+dport_map_port_2=10
+dport_map_port_3=12
+dport_map_port_4=11
+
+#BC8
+portmap_40=65:100:2
+portmap_41=67:100:2
+portmap_42=69:100:2
+portmap_43=71:100:2
+
+dport_map_port_40=16
+dport_map_port_41=15
+dport_map_port_42=13
+dport_map_port_43=14
+
+#BC5
+portmap_24=41:100:2
+portmap_25=43:100:2
+portmap_26=45:100:2
+portmap_27=47:100:2
+
+dport_map_port_24=17
+dport_map_port_25=18
+dport_map_port_26=20
+dport_map_port_27=19
+
+#BC13
+portmap_64=105:100:2
+portmap_65=107:100:2
+portmap_66=109:100:2
+portmap_67=111:100:2
+
+dport_map_port_64=24
+dport_map_port_65=23
+dport_map_port_66=21
+dport_map_port_67=22
+
+#BC4
+portmap_20=33:100:2
+portmap_21=35:100:2
+portmap_22=37:100:2
+portmap_23=39:100:2
+
+dport_map_port_20=25
+dport_map_port_21=26
+dport_map_port_22=28
+dport_map_port_23=27
+
+#BC12
+portmap_60=97:100:2
+portmap_61=99:100:2
+portmap_62=101:100:2
+portmap_63=103:100:2
+
+dport_map_port_60=32
+dport_map_port_61=31
+dport_map_port_62=29
+dport_map_port_63=30
+
+#BC17
+portmap_84=137:100:2
+portmap_85=139:100:2
+portmap_86=141:100:2
+portmap_87=143:100:2
+
+dport_map_port_84=33
+dport_map_port_85=34
+dport_map_port_86=36
+dport_map_port_87=35
+
+#BC25
+portmap_124=201:100:2
+portmap_125=203:100:2
+portmap_126=205:100:2
+portmap_127=207:100:2
+
+dport_map_port_124=40
+dport_map_port_125=39
+dport_map_port_126=37
+dport_map_port_127=38
+
+#BC16
+portmap_80=129:100:2
+portmap_81=131:100:2
+portmap_82=133:100:2
+portmap_83=135:100:2
+
+dport_map_port_80=41
+dport_map_port_81=42
+dport_map_port_82=44
+dport_map_port_83=43
+
+#BC24
+portmap_120=193:100:2
+portmap_121=195:100:2
+portmap_122=197:100:2
+portmap_123=199:100:2
+
+dport_map_port_120=48
+dport_map_port_121=47
+dport_map_port_122=45
+dport_map_port_123=46
+
+#BC21
+portmap_104=169:100:2
+portmap_105=171:100:2
+portmap_106=173:100:2
+portmap_107=175:100:2
+
+dport_map_port_104=49
+dport_map_port_105=50
+dport_map_port_106=52
+dport_map_port_107=51
+
+#BC29
+portmap_144=233:100:2
+portmap_145=235:100:2
+portmap_146=237:100:2
+portmap_147=239:100:2
+
+dport_map_port_144=56
+dport_map_port_145=55
+dport_map_port_146=53
+dport_map_port_147=54
+
+#BC20
+portmap_100=161:100:2
+portmap_101=163:100:2
+portmap_102=165:100:2
+portmap_103=167:100:2
+
+dport_map_port_100=57
+dport_map_port_101=58
+dport_map_port_102=60
+dport_map_port_103=59
+
+#BC28
+portmap_140=225:100:2
+portmap_141=227:100:2
+portmap_142=229:100:2
+portmap_143=231:100:2
+
+dport_map_port_140=64
+dport_map_port_141=63
+dport_map_port_142=61
+dport_map_port_143=62
+
+#BC3
+portmap_13=25:100:2
+portmap_14=27:100:2
+portmap_15=29:100:2
+portmap_16=31:100:2
+
+dport_map_port_13=65
+dport_map_port_14=66
+dport_map_port_15=68
+dport_map_port_16=67
+
+#BC11
+portmap_52=89:100:2
+portmap_53=91:100:2
+portmap_54=93:100:2
+portmap_55=95:100:2
+
+dport_map_port_52=72
+dport_map_port_53=71
+dport_map_port_54=69
+dport_map_port_55=70
+
+#BC2
+portmap_9=17:100:2
+portmap_10=19:100:2
+portmap_11=21:100:2
+portmap_12=23:100:2
+
+dport_map_port_9=73
+dport_map_port_10=74
+dport_map_port_11=76
+dport_map_port_12=75
+
+#BC10
+portmap_48=81:100:2
+portmap_49=83:100:2
+portmap_50=85:100:2
+portmap_51=87:100:2
+
+dport_map_port_48=80
+dport_map_port_49=79
+dport_map_port_50=77
+dport_map_port_51=78
+
+#BC7
+portmap_32=57:100:2
+portmap_33=59:100:2
+portmap_34=61:100:2
+portmap_35=63:100:2
+
+dport_map_port_32=81
+dport_map_port_33=82
+dport_map_port_34=84
+dport_map_port_35=83
+
+#BC15
+portmap_72=121:100:2
+portmap_73=123:100:2
+portmap_74=125:100:2
+portmap_75=127:100:2
+
+dport_map_port_72=88
+dport_map_port_73=87
+dport_map_port_74=85
+dport_map_port_75=86
+
+#BC6
+portmap_28=49:100:2
+portmap_29=51:100:2
+portmap_30=53:100:2
+portmap_31=55:100:2
+
+dport_map_port_28=89
+dport_map_port_29=90
+dport_map_port_30=92
+dport_map_port_31=91
+
+#BC14
+portmap_68=113:100:2
+portmap_69=115:100:2
+portmap_70=117:100:2
+portmap_71=119:100:2
+
+dport_map_port_68=96
+dport_map_port_69=95
+dport_map_port_70=93
+dport_map_port_71=94
+
+#BC19
+portmap_92=153:100:2
+portmap_93=155:100:2
+portmap_94=157:100:2
+portmap_95=159:100:2
+
+dport_map_port_92=97
+dport_map_port_93=98
+dport_map_port_94=100
+dport_map_port_95=99
+
+#BC27
+portmap_132=217:100:2
+portmap_133=219:100:2
+portmap_134=221:100:2
+portmap_135=223:100:2
+
+dport_map_port_132=104
+dport_map_port_133=103
+dport_map_port_134=101
+dport_map_port_135=102
+
+#BC18
+portmap_88=145:100:2
+portmap_89=147:100:2
+portmap_90=149:100:2
+portmap_91=151:100:2
+
+dport_map_port_88=105
+dport_map_port_89=106
+dport_map_port_90=108
+dport_map_port_91=107
+
+#BC26
+portmap_128=209:100:2
+portmap_129=211:100:2
+portmap_130=213:100:2
+portmap_131=215:100:2
+
+dport_map_port_128=112
+dport_map_port_129=111
+dport_map_port_130=109
+dport_map_port_131=110
+
+#BC23
+portmap_112=185:100:2
+portmap_113=187:100:2
+portmap_114=189:100:2
+portmap_115=191:100:2
+
+dport_map_port_112=113
+dport_map_port_113=114
+dport_map_port_114=116
+dport_map_port_115=115
+
+#BC31
+portmap_152=249:100:2
+portmap_153=251:100:2
+portmap_154=253:100:2
+portmap_155=255:100:2
+
+dport_map_port_152=120
+dport_map_port_153=119
+dport_map_port_154=117
+dport_map_port_155=118
+
+#BC22
+portmap_108=177:100:2
+portmap_109=179:100:2
+portmap_110=181:100:2
+portmap_111=183:100:2
+
+dport_map_port_108=121
+dport_map_port_109=122
+dport_map_port_110=124
+dport_map_port_111=123
+
+#BC30
+portmap_148=241:100:2
+portmap_149=243:100:2
+portmap_150=245:100:2
+portmap_151=247:100:2
+
+dport_map_port_148=128
+dport_map_port_149=127
+dport_map_port_150=125
+dport_map_port_151=126
+
+#BC1
+phy_chain_rx_lane_map_physical{9.0}=0x13026475
+phy_chain_tx_lane_map_physical{9.0}=0x21340756
+
+#BC9
+phy_chain_rx_lane_map_physical{73.0}=0x47560213
+phy_chain_tx_lane_map_physical{73.0}=0x76540132
+
+#BC0
+phy_chain_rx_lane_map_physical{1.0}=0x20314657
+phy_chain_tx_lane_map_physical{1.0}=0x32014567
+
+#BC8
+phy_chain_rx_lane_map_physical{65.0}=0x13025647
+phy_chain_tx_lane_map_physical{65.0}=0x13204675
+
+#BC5
+phy_chain_rx_lane_map_physical{41.0}=0x31207564
+phy_chain_tx_lane_map_physical{41.0}=0x23104567
+
+#BC13
+phy_chain_rx_lane_map_physical{105.0}=0x63725140
+phy_chain_tx_lane_map_physical{105.0}=0x76541032
+
+#BC4
+phy_chain_rx_lane_map_physical{33.0}=0x76452031
+phy_chain_tx_lane_map_physical{33.0}=0x67450123
+
+#BC12
+phy_chain_rx_lane_map_physical{97.0}=0x31206574
+phy_chain_tx_lane_map_physical{97.0}=0x31025467
+
+#BC17
+phy_chain_rx_lane_map_physical{137.0}=0x13025746
+phy_chain_tx_lane_map_physical{137.0}=0x23410576
+
+#BC25
+phy_chain_rx_lane_map_physical{201.0}=0x47560213
+phy_chain_tx_lane_map_physical{201.0}=0x67450231
+
+#BC16
+phy_chain_rx_lane_map_physical{129.0}=0x30214657
+phy_chain_tx_lane_map_physical{129.0}=0x13427065
+
+#BC24
+phy_chain_rx_lane_map_physical{193.0}=0x13025647
+phy_chain_tx_lane_map_physical{193.0}=0x23104675
+
+#BC21
+phy_chain_rx_lane_map_physical{169.0}=0x31206574
+phy_chain_tx_lane_map_physical{169.0}=0x13205476
+
+#BC29
+phy_chain_rx_lane_map_physical{233.0}=0x65741302
+phy_chain_tx_lane_map_physical{233.0}=0x57610423
+
+#BC20
+phy_chain_rx_lane_map_physical{161.0}=0x74652031
+phy_chain_tx_lane_map_physical{161.0}=0x57640132
+
+#BC28
+phy_chain_rx_lane_map_physical{225.0}=0x16072435
+phy_chain_tx_lane_map_physical{225.0}=0x43127065
+
+#BC3 laneswap
+phy_chain_rx_lane_map_physical{25.0}=0x36271504
+phy_chain_tx_lane_map_physical{25.0}=0x13204576
+
+#BC11
+phy_chain_rx_lane_map_physical{89.0}=0x47560213
+phy_chain_tx_lane_map_physical{89.0}=0x76540132
+
+#BC2
+phy_chain_rx_lane_map_physical{17.0}=0x43507162
+phy_chain_tx_lane_map_physical{17.0}=0x46570123
+
+#BC10
+phy_chain_rx_lane_map_physical{81.0}=0x13025647
+phy_chain_tx_lane_map_physical{81.0}=0x13204675
+
+#BC7
+phy_chain_rx_lane_map_physical{57.0}=0x31207564
+phy_chain_tx_lane_map_physical{57.0}=0x23406175
+
+#BC15
+phy_chain_rx_lane_map_physical{121.0}=0x13026475
+phy_chain_tx_lane_map_physical{121.0}=0x23507614
+
+#BC6
+phy_chain_rx_lane_map_physical{49.0}=0x65742031
+phy_chain_tx_lane_map_physical{49.0}=0x57640231
+
+#BC14
+phy_chain_rx_lane_map_physical{113.0}=0x02136574
+phy_chain_tx_lane_map_physical{113.0}=0x12436075
+
+#BC19
+phy_chain_rx_lane_map_physical{153.0}=0x40516273
+phy_chain_tx_lane_map_physical{153.0}=0x32045671
+
+#BC27
+phy_chain_rx_lane_map_physical{217.0}=0x64570213
+phy_chain_tx_lane_map_physical{217.0}=0x67054123
+
+#BC18
+phy_chain_rx_lane_map_physical{145.0}=0x46570213
+phy_chain_tx_lane_map_physical{145.0}=0x57063421
+
+#BC26
+phy_chain_rx_lane_map_physical{209.0}=0x13025647
+phy_chain_tx_lane_map_physical{209.0}=0x23104675
+
+#BC23
+phy_chain_rx_lane_map_physical{185.0}=0x31207564
+phy_chain_tx_lane_map_physical{185.0}=0x13245076
+
+#BC31
+phy_chain_rx_lane_map_physical{249.0}=0x02137564
+phy_chain_tx_lane_map_physical{249.0}=0x32106457
+
+#BC22
+phy_chain_rx_lane_map_physical{177.0}=0x64752031
+phy_chain_tx_lane_map_physical{177.0}=0x57640132
+
+#BC30
+phy_chain_rx_lane_map_physical{241.0}=0x31204657
+phy_chain_tx_lane_map_physical{241.0}=0x32016457
+
+#BC1
+serdes_core_rx_polarity_flip_physical{9}=0x33
+serdes_core_tx_polarity_flip_physical{9}=0x71
+
+#BC9
+serdes_core_rx_polarity_flip_physical{73}=0x93
+serdes_core_tx_polarity_flip_physical{73}=0xa9
+
+#BC0
+serdes_core_rx_polarity_flip_physical{1}=0xc3
+serdes_core_tx_polarity_flip_physical{1}=0xdf
+
+#BC8
+serdes_core_rx_polarity_flip_physical{65}=0x39
+serdes_core_tx_polarity_flip_physical{65}=0xbe
+
+#BC5
+serdes_core_rx_polarity_flip_physical{41}=0x3c
+serdes_core_tx_polarity_flip_physical{41}=0x6a
+
+#BC13
+serdes_core_rx_polarity_flip_physical{105}=0xc6
+serdes_core_tx_polarity_flip_physical{105}=0xaf
+
+#BC4
+serdes_core_rx_polarity_flip_physical{33}=0x63
+serdes_core_tx_polarity_flip_physical{33}=0x1c
+
+#BC12
+serdes_core_rx_polarity_flip_physical{97}=0x36
+serdes_core_tx_polarity_flip_physical{97}=0x7f
+
+#BC17
+serdes_core_rx_polarity_flip_physical{137}=0x3c
+serdes_core_tx_polarity_flip_physical{137}=0x71
+
+#BC25
+serdes_core_rx_polarity_flip_physical{201}=0x93
+serdes_core_tx_polarity_flip_physical{201}=0x5c
+
+#BC16
+serdes_core_rx_polarity_flip_physical{129}=0x63
+serdes_core_tx_polarity_flip_physical{129}=0x6f
+
+#BC24
+serdes_core_rx_polarity_flip_physical{193}=0x39
+serdes_core_tx_polarity_flip_physical{193}=0x1e
+
+#BC21
+serdes_core_rx_polarity_flip_physical{169}=0x32
+serdes_core_tx_polarity_flip_physical{169}=0xc5
+
+#BC29
+serdes_core_rx_polarity_flip_physical{233}=0x9c
+serdes_core_tx_polarity_flip_physical{233}=0xca
+
+#BC20
+serdes_core_rx_polarity_flip_physical{161}=0x63
+serdes_core_tx_polarity_flip_physical{161}=0x87
+
+#BC28
+serdes_core_rx_polarity_flip_physical{225}=0x21
+serdes_core_tx_polarity_flip_physical{225}=0xca
+
+#Polarity BC3
+serdes_core_rx_polarity_flip_physical{25}=0x89
+serdes_core_tx_polarity_flip_physical{25}=0xcb
+
+#BC11
+serdes_core_rx_polarity_flip_physical{89}=0x93
+serdes_core_tx_polarity_flip_physical{89}=0xb9
+
+#BC2
+serdes_core_rx_polarity_flip_physical{17}=0xc2
+serdes_core_tx_polarity_flip_physical{17}=0x8a
+#BC10
+serdes_core_rx_polarity_flip_physical{81}=0x39
+serdes_core_tx_polarity_flip_physical{81}=0xbe
+
+#BC7
+serdes_core_rx_polarity_flip_physical{57}=0x3c
+serdes_core_tx_polarity_flip_physical{57}=0x6c
+
+#BC15
+serdes_core_rx_polarity_flip_physical{121}=0x33
+serdes_core_tx_polarity_flip_physical{121}=0x47
+
+#BC6
+serdes_core_rx_polarity_flip_physical{49}=0x93
+serdes_core_tx_polarity_flip_physical{49}=0x82
+
+#BC14
+serdes_core_rx_polarity_flip_physical{113}=0x86
+serdes_core_tx_polarity_flip_physical{113}=0x08
+
+#BC19
+serdes_core_rx_polarity_flip_physical{153}=0x66
+serdes_core_tx_polarity_flip_physical{153}=0xc6
+
+#BC27
+serdes_core_rx_polarity_flip_physical{217}=0xc3
+serdes_core_tx_polarity_flip_physical{217}=0x52
+
+#BC18
+serdes_core_rx_polarity_flip_physical{145}=0xc3
+serdes_core_tx_polarity_flip_physical{145}=0xef
+
+#BC26
+serdes_core_rx_polarity_flip_physical{209}=0x39
+serdes_core_tx_polarity_flip_physical{209}=0x3e
+
+#BC23
+serdes_core_rx_polarity_flip_physical{185}=0x3c
+serdes_core_tx_polarity_flip_physical{185}=0xd5
+
+#BC31
+serdes_core_rx_polarity_flip_physical{249}=0xcc
+serdes_core_tx_polarity_flip_physical{249}=0xac
+
+#BC22
+serdes_core_rx_polarity_flip_physical{177}=0xc3
+serdes_core_tx_polarity_flip_physical{177}=0x83
+
+#BC30
+serdes_core_rx_polarity_flip_physical{241}=0x33
+serdes_core_tx_polarity_flip_physical{241}=0x2d
+
+core_clock_frequency=1325
+dpr_clock_frequency=1000
+device_clock_frequency=1325
+port_flex_enable=1
+
+#firmware load method, use fast load
+load_firmware=0x2
+
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/.installer.conf.swp b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/.installer.conf.swp
new file mode 100644
index 000000000000..e85feb00996a
Binary files /dev/null and b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/.installer.conf.swp differ
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/AS14-40D/port_config.ini b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/AS14-40D/port_config.ini
new file mode 100644
index 000000000000..5c6ca5db0a7b
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/AS14-40D/port_config.ini
@@ -0,0 +1,33 @@
+# name lanes alias index
+Ethernet1 1,2,3,4 QSFP1 1
+Ethernet2 5,6,7,8 QSFP2 2
+Ethernet3 9,10,11,12 QSFP3 3
+Ethernet4 13,14,15,16 QSFP4 4
+Ethernet5 17,18,19,20 QSFP5 5
+Ethernet6 21,22,23,24 QSFP6 6
+Ethernet7 25,26,27,28 QSFP7 7
+Ethernet8 29,30,31,32 QSFP8 8
+Ethernet9 33,34,35,36 QSFP9 9
+Ethernet10 37,38,39,40 QSFP10 10
+Ethernet11 41,42,43,44 QSFP11 11
+Ethernet12 45,46,47,48 QSFP12 12
+Ethernet13 49,50,51,52 QSFP13 13
+Ethernet14 53,54,55,56 QSFP14 14
+Ethernet15 57,58,59,60 QSFP15 15
+Ethernet16 61,62,63,64 QSFP16 16
+Ethernet17 65,66,67,68 QSFP17 17
+Ethernet18 69,70,71,72 QSFP18 18
+Ethernet19 73,74,75,76 QSFP19 19
+Ethernet20 77,78,79,80 QSFP20 20
+Ethernet21 81,82,83,84 QSFP21 21
+Ethernet22 85,86,87,88 QSFP22 22
+Ethernet23 89,90,91,92 QSFP23 23
+Ethernet24 93,94,95,96 QSFP24 24
+Ethernet25 97,98,99,100 QSFP25 25
+Ethernet26 101,102,103,104 QSFP26 26
+Ethernet27 105,106,107,108 QSFP27 27
+Ethernet28 109,110,111,112 QSFP28 28
+Ethernet29 113,114,115,116 QSFP29 29
+Ethernet30 117,118,119,120 QSFP30 30
+Ethernet31 121,122,123,124 QSFP31 31
+Ethernet32 125,126,127,128 QSFP32 32
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/AS14-40D/sai.profile b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/AS14-40D/sai.profile
new file mode 100644
index 000000000000..a4240891e387
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/AS14-40D/sai.profile
@@ -0,0 +1 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/td3-as14-40d.config.bcm
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/custom_led.bin b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/custom_led.bin
new file mode 100644
index 000000000000..91552022dc6f
Binary files /dev/null and b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/custom_led.bin differ
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/default_sku b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/default_sku
new file mode 100644
index 000000000000..93cd11afaefb
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/default_sku
@@ -0,0 +1 @@
+AS14-40D t1
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/installer.conf b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/installer.conf
new file mode 100644
index 000000000000..3f23040c648f
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/installer.conf
@@ -0,0 +1,3 @@
+CONSOLE_SPEED=9600
+ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="processor.max_cstate=1 intel_idle.max_cstate=0
+ processor.max_pstate=1 intel_idle.max_pstate=0"
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/led_proc_init.soc b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/led_proc_init.soc
new file mode 100644
index 000000000000..28cd4b9bc9f7
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/led_proc_init.soc
@@ -0,0 +1,9 @@
+#Enable all ports
+#port all en=1
+#sleep 6
+#linkscan 250000; port xe,ce linkscan=on
+
+#Load LED
+#led auto on; led start
+
+
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/linkscan_led_fw.bin b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/linkscan_led_fw.bin
new file mode 100644
index 000000000000..a6a4794ecc2b
Binary files /dev/null and b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/linkscan_led_fw.bin differ
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/minigraph.xml b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/minigraph.xml
new file mode 100644
index 000000000000..5e95b6ecafe9
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/minigraph.xml
@@ -0,0 +1,854 @@
+
+
+
+
+
+ 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
+
+
+
+
+
+ QSFP1
+ 10.0.0.0/31
+
+
+
+ QSFP2
+ 10.0.0.2/31
+
+
+
+ QSFP3
+ 10.0.0.4/31
+
+
+
+ QSFP4
+ 10.0.0.6/31
+
+
+
+ QSFP5
+ 10.0.0.8/31
+
+
+
+ QSFP6
+ 10.0.0.10/31
+
+
+
+ QSFP7
+ 10.0.0.12/31
+
+
+
+ QSFP8
+ 10.0.0.14/31
+
+
+
+ QSFP9
+ 10.0.0.16/31
+
+
+
+ QSFP10
+ 10.0.0.18/31
+
+
+
+ QSFP11
+ 10.0.0.20/31
+
+
+
+ QSFP12
+ 10.0.0.22/31
+
+
+
+ QSFP13
+ 10.0.0.24/31
+
+
+
+ QSFP14
+ 10.0.0.26/31
+
+
+
+ QSFP15
+ 10.0.0.28/31
+
+
+
+ QSFP16
+ 10.0.0.30/31
+
+
+
+ QSFP17
+ 10.0.0.32/31
+
+
+
+ QSFP18
+ 10.0.0.34/31
+
+
+
+ QSFP19
+ 10.0.0.36/31
+
+
+
+ QSFP20
+ 10.0.0.38/31
+
+
+
+ QSFP21
+ 10.0.0.40/31
+
+
+
+ QSFP22
+ 10.0.0.42/31
+
+
+
+ QSFP23
+ 10.0.0.44/31
+
+
+
+ QSFP24
+ 10.0.0.46/31
+
+
+
+ QSFP25
+ 10.0.0.48/31
+
+
+
+ QSFP26
+ 10.0.0.50/31
+
+
+
+ QSFP27
+ 10.0.0.52/31
+
+
+
+ QSFP28
+ 10.0.0.54/31
+
+
+
+ QSFP29
+ 10.0.0.56/31
+
+
+
+ QSFP30
+ 10.0.0.58/31
+
+
+
+ QSFP31
+ 10.0.0.60/31
+
+
+
+ QSFP32
+ 10.0.0.62/31
+
+
+
+
+
+
+
+
+
+
+
+
+ sonic
+ AS14-40D
+
+
+
+
+
+
+ sonic
+
+
+ DhcpResources
+
+
+
+
+ NtpResources
+
+ 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org
+
+
+ SyslogResources
+
+
+
+
+ ErspanDestinationIpv4
+
+ 2.2.2.2
+
+
+
+
+
+
+ sonic
+ AS14-40D
+
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/opennsl-postinit.cfg b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/opennsl-postinit.cfg
new file mode 100644
index 000000000000..7008c14c0ffc
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/opennsl-postinit.cfg
@@ -0,0 +1,3 @@
+linkscan 250000; port xe,ce linkscan=on
+sleep 1
+led auto on; led start
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/cputemputil.py b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/cputemputil.py
new file mode 100644
index 000000000000..ac2589d044fd
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/cputemputil.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+#
+# cputemputil.py
+#
+# Platform-specific CPU temperature Interface for SONiC
+#
+
+__author__ = 'Wirut G.'
+__license__ = "GPL"
+__version__ = "0.1.0"
+__status__ = "Development"
+
+
+import subprocess
+import requests
+
+
+class CpuTempUtil():
+ """Platform-specific CpuTempUtil class"""
+
+ def __init__(self):
+ pass
+
+ def get_cpu_temp(self):
+
+ # Get list of temperature of CPU cores.
+ p = subprocess.Popen(['sensors', '-Au', 'coretemp-isa-0000'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ raw_data_list = out.splitlines()
+ temp_string_list = [i for i, s in enumerate(
+ raw_data_list) if '_input' in s]
+ tmp_list = [0]
+
+ for temp_string in temp_string_list:
+ tmp_list.append(float(raw_data_list[temp_string].split(":")[1]))
+
+ return tmp_list
+
+ def get_max_cpu_tmp(self):
+ # Get maximum temperature from list of temperature of CPU cores.
+ return max(self.get_cpu_temp())
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/eeprom.py b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/eeprom.py
new file mode 100644
index 000000000000..9f42b56ce7c2
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/eeprom.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Celestica DX010
+#
+# Platform and model specific eeprom subclass, inherits from the base class,
+# and provides the followings:
+# - the eeprom format definition
+# - specific encoder/decoder if there is special need
+#############################################################################
+
+try:
+ from sonic_eeprom import eeprom_tlvinfo
+except ImportError, e:
+ raise ImportError (str(e) + "- required module not found")
+
+
+class board(eeprom_tlvinfo.TlvInfoDecoder):
+
+ def __init__(self, name, path, cpld_root, ro):
+ self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom"
+ super(board, self).__init__(self.eeprom_path, 0, '', True)
+
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/fanutil.py b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/fanutil.py
new file mode 100644
index 000000000000..dab2f64dd5e0
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/fanutil.py
@@ -0,0 +1,310 @@
+#!/usr/bin/env python
+
+__author__ = 'Wirut G.'
+__license__ = "GPL"
+__version__ = "0.1.2"
+__status__ = "Development"
+
+import requests
+import re
+
+
+class FanUtil():
+ """Platform-specific FanUtil class"""
+
+ def __init__(self):
+
+ self.fan_fru_url = "http://240.1.1.1:8080/api/sys/fruid/fan"
+ self.sensor_url = "http://240.1.1.1:8080/api/sys/sensors"
+ self.fru_data_list = None
+ self.sensor_data_list = None
+
+ def request_data(self):
+ # Reqest data from BMC if not exist.
+ if self.fru_data_list is None or self.sensor_data_list is None:
+ fru_data_req = requests.get(self.fan_fru_url)
+ sensor_data_req = requests.get(self.sensor_url)
+ fru_json = fru_data_req.json()
+ sensor_json = sensor_data_req.json()
+ self.fru_data_list = fru_json.get('Information')
+ self.sensor_data_list = sensor_json.get('Information')
+ return self.fru_data_list, self.sensor_data_list
+
+ def name_to_index(self, fan_name):
+ # Get fan index from fan name
+ match = re.match(r"(FAN)([0-9]+)-(1|2)", fan_name, re.I)
+ fan_index = None
+ if match:
+ i_list = list(match.groups())
+ fan_index = int(i_list[1])*2 - (int(i_list[2]) % 2)
+ return fan_index
+
+ def get_num_fans(self):
+ """
+ Get the number of fans
+ :return: int num_fans
+ """
+ num_fans = 8
+
+ return num_fans
+
+ def get_fan_speed(self, fan_name):
+ """
+ Get the current speed of the fan, the unit is "RPM"
+ :return: int fan_speed
+ """
+
+ try:
+ # Get real fan index
+ index = self.name_to_index(fan_name)
+
+ # Set key and index.
+ fan_speed = 0
+ position_key = "Front" if index % 2 != 0 else "Rear"
+ index = int(round(float(index)/2))
+ fan_key = "Fan " + str(index) + " " + position_key
+
+ # Request and validate fan information.
+ self.fru_data_list, self.sensor_data_list = self.request_data()
+
+ # Get fan's speed.
+ for sensor_data in self.sensor_data_list:
+ sensor_name = sensor_data.get('name')
+ if "fan" in str(sensor_name):
+ fan_data = sensor_data.get(fan_key)
+ fan_sp_list = map(int, re.findall(r'\d+', fan_data))
+ fan_speed = fan_sp_list[0]
+
+ except:
+ return 0
+
+ return fan_speed
+
+ def get_fan_low_threshold(self, fan_name):
+ """
+ Get the low speed threshold of the fan.
+ if the current speed < low speed threshold,
+ the status of the fan is not ok.
+ :return: int fan_low_threshold
+ """
+
+ try:
+ # Get real fan index
+ index = self.name_to_index(fan_name)
+
+ # Set key and index.
+ fan_low_threshold = 0
+ position_key = "Front" if index % 2 != 0 else "Rear"
+ index = int(round(float(index)/2))
+ fan_key = "Fan " + str(index) + " " + position_key
+
+ # Request and validate fan information.
+ self.fru_data_list, self.sensor_data_list = self.request_data()
+
+ # Get fan's threshold.
+ for sensor_data in self.sensor_data_list:
+ sensor_name = sensor_data.get('name')
+ if "fan" in str(sensor_name):
+ fan_data = sensor_data.get(fan_key)
+ fan_sp_list = map(int, re.findall(r'\d+', fan_data))
+ fan_low_threshold = fan_sp_list[1]
+
+ except:
+ return "N/A"
+
+ return fan_low_threshold
+
+ def get_fan_high_threshold(self, fan_name):
+ """
+ Get the hight speed threshold of the fan,
+ if the current speed > high speed threshold,
+ the status of the fan is not ok
+ :return: int fan_high_threshold
+ """
+
+ try:
+ # Get real fan index
+ index = self.name_to_index(fan_name)
+
+ # Set key and index.
+ fan_high_threshold = 0
+ position_key = "Front" if index % 2 != 0 else "Rear"
+ index = int(round(float(index)/2))
+ fan_key = "Fan " + str(index) + " " + position_key
+
+ # Request and validate fan information.
+ self.fru_data_list, self.sensor_data_list = self.request_data()
+
+ # Get fan's threshold.
+ for sensor_data in self.sensor_data_list:
+ sensor_name = sensor_data.get('name')
+ if "fan" in str(sensor_name):
+ fan_data = sensor_data.get(fan_key)
+ fan_sp_list = map(int, re.findall(r'\d+', fan_data))
+ fan_high_threshold = fan_sp_list[2]
+
+ except:
+ return 0
+
+ return fan_high_threshold
+
+ def get_fan_pn(self, fan_name):
+ """
+ Get the product name of the fan
+ :return: str fan_pn
+ """
+
+ try:
+ # Get real fan index
+ index = self.name_to_index(fan_name)
+
+ # Set key and index.
+ fan_pn = "N/A"
+ index = int(round(float(index)/2))
+ fan_fru_key = "Fantray" + str(index)
+
+ # Request and validate fan information.
+ self.fru_data_list, self.sensor_data_list = self.request_data()
+
+ # Get fan's fru.
+ for fan_fru in self.fru_data_list:
+ matching_fan = [s for s in fan_fru if fan_fru_key in s]
+ if matching_fan:
+ pn = [s for s in fan_fru if "Part" in s]
+ fan_pn = pn[0].split()[4]
+
+ except:
+ return "N/A"
+
+ return fan_pn
+
+ def get_fan_sn(self, fan_name):
+ """
+ Get the serial number of the fan
+ :return: str fan_sn
+ """
+ try:
+ # Get real fan index
+ index = self.name_to_index(fan_name)
+
+ # Set key and index.
+ fan_sn = "N/A"
+ index = int(round(float(index)/2))
+ fan_fru_key = "Fantray" + str(index)
+
+ # Request and validate fan information.
+ self.fru_data_list, self.sensor_data_list = self.request_data()
+
+ # Get fan's fru.
+ for fan_fru in self.fru_data_list:
+ matching_fan = [s for s in fan_fru if fan_fru_key in s]
+ if matching_fan:
+ serial = [s for s in fan_fru if "Serial" in s]
+ fan_sn = serial[0].split()[3]
+
+ except:
+ return "N/A"
+
+ return fan_sn
+
+ def get_fans_name_list(self):
+ """
+ Get list of fan name.
+ :return: list fan_names
+ """
+ fan_names = []
+
+ # Get the number of fans
+ n_fan = self.get_num_fans()
+
+ # Set fan name and add to the list.
+ for x in range(1, n_fan + 1):
+ f_index = int(round(float(x)/2))
+ pos = 1 if x % 2 else 2
+ fan_name = 'FAN{}_{}'.format(f_index, pos)
+ fan_names.append(fan_name)
+
+ return fan_names
+
+ def get_all(self):
+ """
+ Get all information of system FANs, returns JSON objects in python 'DICT'.
+ Number, mandatory, max number of FAN, integer
+ FAN1_1, FAN1_2, ... mandatory, FAN name, string
+ Present, mandatory for each FAN, present status, boolean, True for present, False for NOT present, read directly from h/w
+ Running, conditional, if PRESENT is True, running status of the FAN, True for running, False for stopped, read directly from h/w
+ Speed, conditional, if PRESENT is True, real FAN speed, float, read directly from h/w
+ LowThd, conditional, if PRESENT is True, lower bound of FAN speed, float, read from h/w
+ HighThd, conditional, if PRESENT is True, upper bound of FAN speed, float, read from h/w
+ PN, conditional, if PRESENT is True, PN of the FAN, string
+ SN, conditional, if PRESENT is True, SN of the FAN, string)
+ """
+
+ self.fru_data_list, self.sensor_data_list = self.request_data()
+ all_fan_dict = dict()
+
+ # Get the number of fans
+ n_fan = self.get_num_fans()
+ all_fan_dict["Number"] = n_fan
+
+ # Set fan FRU data.
+ fan_fru_dict = dict()
+ fan_raw_idx = 1
+ for fan_fru in self.fru_data_list:
+ fru_dict = dict()
+ fan_ps = False
+
+ if len(fan_fru) == 0:
+ fan_idx = fan_raw_idx
+ fan_pn = "N/A"
+ fan_sn = "N/A"
+ else:
+ fan_key = fan_fru[0].split()
+ if str(fan_key[-1]).lower() == "absent":
+ fan_idx = int(re.findall('\d+', fan_key[0])[0])
+
+ else:
+ fan_idx = int(re.findall('\d+', fan_key[-1])[0])
+ fan_ps = True
+ pn = [s for s in fan_fru if "Part" in s]
+ sn = [s for s in fan_fru if "Serial" in s]
+ fan_pn = pn[0].split(
+ ":")[-1].strip() if len(pn) > 0 else 'N/A'
+ fan_sn = sn[0].split(
+ ":")[-1].strip() if len(sn) > 0 else 'N/A'
+
+ fru_dict["PN"] = "N/A" if not fan_pn or fan_pn == "" else fan_pn
+ fru_dict["SN"] = "N/A" if not fan_sn or fan_sn == "" else fan_sn
+ fru_dict["Present"] = fan_ps
+ fan_fru_dict[fan_idx] = fru_dict
+ fan_raw_idx += 1
+
+ # Set fan sensor data.
+ for sensor_data in self.sensor_data_list:
+ sensor_name = sensor_data.get('name')
+ if "fan" in str(sensor_name):
+ for x in range(1, n_fan + 1):
+ fan_dict = dict()
+ f_index = int(round(float(x)/2))
+ pos = 1 if x % 2 else 2
+ position_key = "Front" if x % 2 != 0 else "Rear"
+ fan_key = "Fan " + str(f_index) + " " + position_key
+ fan_data = sensor_data.get(fan_key)
+ fan_sp_list = map(int, re.findall(r'\d+', fan_data))
+ fan_dict["Present"] = fan_fru_dict[f_index]["Present"]
+ if fan_dict["Present"] or fan_sp_list[0] > 0:
+ fan_dict["Present"] = True
+ fan_dict["Speed"] = fan_sp_list[0]
+ fan_dict["Running"] = True if fan_dict["Speed"] > 0 else False
+ fan_dict["LowThd"] = fan_sp_list[1]
+ fan_dict["HighThd"] = fan_sp_list[2]
+ fan_dict["PN"] = fan_fru_dict[f_index]["PN"]
+ fan_dict["SN"] = fan_fru_dict[f_index]["SN"]
+ fan_dict["AirFlow"] = "FTOB" if "R1241-F9001" in fan_dict["PN"] else "Unknown"
+ fan_dict["AirFlow"] = "BTOF" if "R1241-F9002" in fan_dict["PN"] else fan_dict["AirFlow"]
+ fan_dict["Status"] = True if fan_dict["AirFlow"] != "Unknown" else False
+ fan_name = 'FAN{}_{}'.format(f_index, pos)
+ all_fan_dict[fan_name] = fan_dict
+ break
+
+ return all_fan_dict
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/fwmgrutil.py b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/fwmgrutil.py
new file mode 100644
index 000000000000..c1fb40cebfb8
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/fwmgrutil.py
@@ -0,0 +1,882 @@
+# fwmgrutil.py
+#
+# Platform-specific firmware management interface for SONiC
+#
+
+import subprocess
+import requests
+import os
+import pexpect
+import base64
+import time
+import json
+import logging
+import ast
+from datetime import datetime
+
+try:
+ from sonic_fwmgr.fwgmr_base import FwMgrUtilBase
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
+
+
+class FwMgrUtil(FwMgrUtilBase):
+
+ """Platform-specific FwMgrUtil class"""
+
+ def __init__(self):
+ self.platform_name = "AS1332h"
+ self.onie_config_file = "/host/machine.conf"
+ self.bmc_info_url = "http://240.1.1.1:8080/api/sys/bmc"
+ self.bmc_raw_command_url = "http://240.1.1.1:8080/api/sys/raw"
+ self.fw_upgrade_url = "http://240.1.1.1:8080/api/sys/upgrade"
+ self.onie_config_file = "/host/machine.conf"
+ self.fw_upgrade_logger_path = "/var/log/fw_upgrade.log"
+ self.cpldb_version_path = "/sys/devices/platform/%s.cpldb/getreg" % self.platform_name
+ self.fpga_version_path = "/sys/devices/platform/%s.switchboard/FPGA/getreg" % self.platform_name
+ self.switchboard_cpld1_path = "/sys/devices/platform/%s.switchboard/CPLD1/getreg" % self.platform_name
+ self.switchboard_cpld2_path = "/sys/devices/platform/%s.switchboard/CPLD2/getreg" % self.platform_name
+ self.switchboard_cpld3_path = "/sys/devices/platform/%s.switchboard/CPLD3/getreg" % self.platform_name
+ self.switchboard_cpld4_path = "/sys/devices/platform/%s.switchboard/CPLD4/getreg" % self.platform_name
+ self.bmc_pwd_path = "/usr/local/etc/bmcpwd"
+
+ def __get_register_value(self, path, register):
+ cmd = "echo {1} > {0}; cat {0}".format(path, register)
+ p = subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ raw_data, err = p.communicate()
+ if err is not '':
+ return 'None'
+ else:
+ return raw_data.strip()
+
+ def __update_fw_upgrade_logger(self, header, message):
+ if not os.path.isfile(self.fw_upgrade_logger_path):
+ cmd = "sudo touch %s && sudo chmod +x %s" % (
+ self.fw_upgrade_logger_path, self.fw_upgrade_logger_path)
+ subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ logging.basicConfig(filename=self.fw_upgrade_logger_path,
+ filemode='a',
+ format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
+ datefmt='%b %d %H:%M:%S',
+ level=logging.INFO)
+
+ log_message = "%s : %s" % (header, message)
+ if header != "last_upgrade_result":
+ print(log_message)
+ return logging.info(log_message)
+
+ def get_bmc_pass(self):
+ if os.path.exists(self.bmc_pwd_path):
+ with open(self.bmc_pwd_path) as file:
+ data = file.read()
+
+ key = "bmc"
+ dec = []
+ enc = base64.urlsafe_b64decode(data)
+ for i in range(len(enc)):
+ key_c = key[i % len(key)]
+ dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
+ dec.append(dec_c)
+ return "".join(dec)
+ return False
+
+ def get_bmc_version(self):
+ """Get BMC version from SONiC
+ :returns: version string
+
+ """
+ bmc_version = None
+
+ bmc_version_key = "OpenBMC Version"
+ bmc_info_req = requests.get(self.bmc_info_url, timeout=60)
+ if bmc_info_req.status_code == 200:
+ bmc_info_json = bmc_info_req.json()
+ bmc_info = bmc_info_json.get('Information')
+ bmc_version = bmc_info.get(bmc_version_key)
+ return str(bmc_version)
+
+ def upload_file_bmc(self, fw_path):
+ scp_command = 'sudo scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -r %s root@240.1.1.1:/home/root/' % os.path.abspath(
+ fw_path)
+ child = pexpect.spawn(scp_command)
+ i = child.expect(["root@240.1.1.1's password:"], timeout=30)
+ bmc_pwd = self.get_bmc_pass()
+ if i == 0 and bmc_pwd:
+ child.sendline(bmc_pwd)
+ data = child.read()
+ print(data)
+ child.close
+ return os.path.isfile(fw_path)
+ return False
+
+ def get_cpld_version(self):
+ """Get CPLD version from SONiC
+ :returns: dict like {'CPLD_1': version_string, 'CPLD_2': version_string}
+ """
+
+ CPLD_B = self.__get_register_value(self.cpldb_version_path, '0xA100')
+ CPLD_C = self.__get_register_value(self.cpldb_version_path, '0xA1E0')
+ CPLD_1 = self.__get_register_value(self.switchboard_cpld1_path, '0x00')
+ CPLD_2 = self.__get_register_value(self.switchboard_cpld2_path, '0x00')
+ CPLD_3 = self.__get_register_value(self.switchboard_cpld3_path, '0x00')
+ CPLD_4 = self.__get_register_value(self.switchboard_cpld4_path, '0x00')
+
+ fan_cpld_key = "FanCPLD Version"
+ fan_cpld = None
+ bmc_info_req = requests.get(self.bmc_info_url)
+ if bmc_info_req.status_code == 200:
+ bmc_info_json = bmc_info_req.json()
+ bmc_info = bmc_info_json.get('Information')
+ fan_cpld = bmc_info.get(fan_cpld_key)
+
+ CPLD_B = 'None' if CPLD_B is 'None' else "{}.{}".format(
+ int(CPLD_B[2], 16), int(CPLD_B[3], 16))
+ CPLD_C = 'None' if CPLD_C is 'None' else "{}.{}".format(
+ int(CPLD_C[2], 16), int(CPLD_C[3], 16))
+ CPLD_1 = 'None' if CPLD_1 is 'None' else "{}.{}".format(
+ int(CPLD_1[2], 16), int(CPLD_1[3], 16))
+ CPLD_2 = 'None' if CPLD_2 is 'None' else "{}.{}".format(
+ int(CPLD_2[2], 16), int(CPLD_2[3], 16))
+ CPLD_3 = 'None' if CPLD_3 is 'None' else "{}.{}".format(
+ int(CPLD_3[2], 16), int(CPLD_3[3], 16))
+ CPLD_4 = 'None' if CPLD_4 is 'None' else "{}.{}".format(
+ int(CPLD_4[2], 16), int(CPLD_4[3], 16))
+ FAN_CPLD = 'None' if fan_cpld is None else "{}.{}".format(
+ int(fan_cpld[0], 16), int(fan_cpld[1], 16))
+
+ cpld_version_dict = {}
+ cpld_version_dict.update({'CPLD_B': CPLD_B})
+ cpld_version_dict.update({'CPLD_C': CPLD_C})
+ cpld_version_dict.update({'CPLD_1': CPLD_1})
+ cpld_version_dict.update({'CPLD_2': CPLD_2})
+ cpld_version_dict.update({'CPLD_3': CPLD_3})
+ cpld_version_dict.update({'CPLD_4': CPLD_4})
+ cpld_version_dict.update({'CPLD_FAN': FAN_CPLD})
+
+ return cpld_version_dict
+
+ def get_bios_version(self):
+ """Get BIOS version from SONiC
+ :returns: version string
+
+ """
+ bios_version = None
+
+ p = subprocess.Popen(
+ ["sudo", "dmidecode", "-s", "bios-version"], stdout=subprocess.PIPE)
+ raw_data = str(p.communicate()[0])
+ if raw_data == '':
+ return str(None)
+ raw_data_list = raw_data.split("\n")
+ bios_version = raw_data_list[0] if len(
+ raw_data_list) == 1 else raw_data_list[-2]
+
+ return str(bios_version)
+
+ def get_onie_version(self):
+ """Get ONiE version from SONiC
+ :returns: version string
+
+ """
+ onie_verison = None
+
+ onie_version_keys = "onie_version"
+ onie_config_file = open(self.onie_config_file, "r")
+ for line in onie_config_file.readlines():
+ if onie_version_keys in line:
+ onie_version_raw = line.split('=')
+ onie_verison = onie_version_raw[1].strip()
+ break
+ onie_config_file.close()
+ return str(onie_verison)
+
+ def get_pcie_version(self):
+ """Get PCiE version from SONiC
+ :returns: version dict { "PCIE_FW_LOADER": "2.5", "PCIE_FW": "D102_08" }
+
+ """
+ cmd = "sudo bcmcmd 'pciephy fw version'"
+ p = subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ raw_data, err = p.communicate()
+
+ pcie_version = dict()
+ pcie_version["PCIE_FW_LOADER"] = 'None'
+ pcie_version["PCIE_FW"] = 'None'
+
+ if err == '':
+ lines = raw_data.split('\n')
+ for line in lines:
+ if 'PCIe FW loader' in line:
+ pcie_version["PCIE_FW_LOADER"] = line.split(':')[1].strip()
+ elif 'PCIe FW version' in line:
+ pcie_version["PCIE_FW"] = line.split(':')[1].strip()
+ return pcie_version
+
+ def get_fpga_version(self):
+ """Get FPGA version from SONiC
+ :returns: version string
+
+ """
+ version = self.__get_register_value(self.fpga_version_path, '0x00')
+ if version is not 'None':
+ version = "{}.{}".format(
+ int(version[2:][:4], 16), int(version[2:][4:], 16))
+ return str(version)
+
+ def firmware_upgrade(self, fw_type, fw_path, fw_extra=None):
+ """
+ @fw_type MANDATORY, firmware type, should be one of the strings: 'cpld', 'fpga', 'bios', 'bmc'
+ @fw_path MANDATORY, target firmware file
+ @fw_extra OPTIONAL, extra information string,
+
+ for fw_type 'cpld' and 'fpga': it can be used to indicate specific cpld, such as 'cpld1', 'cpld2', ...
+ or 'cpld_fan_come_board', etc. If None, upgrade all CPLD/FPGA firmware. for fw_type 'bios' and 'bmc',
+ value should be one of 'master' or 'slave' or 'both'
+ """
+ fw_type = fw_type.lower()
+ bmc_pwd = self.get_bmc_pass()
+ if not bmc_pwd and fw_type != "fpga":
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=BMC credential not found")
+ return False
+
+ if fw_type == 'bmc':
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "start BMC upgrade")
+ # Copy BMC image file to BMC
+ fw_extra_str = str(fw_extra).lower()
+ last_fw_upgrade = ["BMC", fw_path, fw_extra_str, "FAILED"]
+ upload_file = self.upload_file_bmc(fw_path)
+ if not upload_file:
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=unable to upload BMC image to BMC")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ filename_w_ext = os.path.basename(fw_path)
+ json_data = dict()
+ json_data["path"] = "root@127.0.0.1:/home/root/%s" % filename_w_ext
+ json_data["password"] = bmc_pwd
+
+ # Set flash type
+ current_bmc = self.get_running_bmc()
+ flash = fw_extra_str if fw_extra_str in [
+ "master", "slave", "both"] else "both"
+ if fw_extra_str == "pingpong":
+ # flash = "master" if current_bmc == "slave" else "slave"
+ flash = "slave"
+ json_data["flash"] = flash
+
+ # Install BMC
+ if flash == "both":
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "install BMC as master mode")
+ json_data["flash"] = "master"
+ r = requests.post(self.bmc_info_url, json=json_data)
+ if r.status_code != 200 or 'success' not in r.json().get('result'):
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "fail, message=BMC API report error code %d" % r.status_code)
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+ json_data["flash"] = "slave"
+
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "install BMC as %s mode" % json_data["flash"])
+ r = requests.post(self.bmc_info_url, json=json_data)
+ if r.status_code == 200 and 'success' in r.json().get('result'):
+ if fw_extra_str == "pingpong":
+ flash = "master" if current_bmc == "slave" else "slave"
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "switch to boot from %s" % flash)
+ self.set_bmc_boot_flash(flash)
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "reboot BMC")
+ if not self.reboot_bmc():
+ return False
+ else:
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "reboot BMC")
+ reboot_dict = {}
+ reboot_dict["reboot"] = "yes"
+ r = requests.post(self.bmc_info_url, json=reboot_dict)
+ last_fw_upgrade[3] = "DONE"
+ else:
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "fail, message=unable to install BMC image")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ self.__update_fw_upgrade_logger(
+ "bmc_upgrade", "done")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return True
+
+ elif fw_type == 'fpga':
+ last_fw_upgrade = ["FPGA", fw_path, None, "FAILED"]
+ self.__update_fw_upgrade_logger(
+ "fpga_upgrade", "start FPGA upgrade")
+
+ if not os.path.isfile(fw_path):
+ self.__update_fw_upgrade_logger(
+ "fpga_upgrade", "fail, message=FPGA image not found %s" % fw_path)
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ command = 'fpga_prog ' + fw_path
+ print("Running command : %s" % command)
+ process = subprocess.Popen(
+ command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ while True:
+ output = process.stdout.readline()
+ if output == '' and process.poll() is not None:
+ break
+
+ rc = process.returncode
+ if rc != 0:
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=unable to install FPGA")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ self.__update_fw_upgrade_logger("fpga_upgrade", "done")
+ last_fw_upgrade[3] = "DONE"
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ self.firmware_refresh(["FPGA"], None, None)
+ return True
+
+ elif 'cpld' in fw_type:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "start CPLD upgrade")
+ # Check input
+ fw_extra_str = str(fw_extra).upper()
+ if ":" in fw_path and ":" in fw_extra_str:
+ fw_path_list = fw_path.split(":")
+ fw_extra_str_list = fw_extra_str.split(":")
+ else:
+ fw_path_list = [fw_path]
+ fw_extra_str_list = [fw_extra_str]
+
+ if len(fw_path_list) != len(fw_extra_str_list):
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=invalid input")
+ return False
+
+ data_list = list(zip(fw_path_list, fw_extra_str_list))
+ refresh_img_path = None
+ cpld_result_list = ["FAILED" for i in range(
+ 0, len(fw_extra_str_list))]
+ last_fw_upgrade = ["CPLD", ":".join(
+ fw_path_list), ":".join(fw_extra_str_list), ":".join(cpld_result_list)]
+ for i in range(0, len(data_list)):
+ data = data_list[i]
+ fw_path = data[0]
+ fw_extra_str = data[1]
+
+ # Set fw_extra
+ fw_extra_str = {
+ "TOP_LC_CPLD": "top_lc",
+ "BOT_LC_CPLD": "bottom_lc",
+ "FAN_CPLD": "fan",
+ "CPU_CPLD": "cpu",
+ "BASE_CPLD": "base",
+ "COMBO_CPLD": "combo",
+ "SW_CPLD1": "switch",
+ "SW_CPLD2": "switch",
+ "REFRESH_CPLD": "refresh"
+ }.get(fw_extra_str, None)
+
+ if fw_extra_str == "refresh":
+ refresh_img_path = fw_path
+ del cpld_result_list[i]
+ del fw_extra_str_list[i]
+ continue
+
+ if fw_extra_str is None:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=invalid extra information string")
+ continue
+
+ # Uploading image to BMC
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "start %s upgrade" % data[1])
+ upload_file = self.upload_file_bmc(fw_path)
+ if not upload_file:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=unable to upload BMC image to BMC")
+ continue
+
+ filename_w_ext = os.path.basename(fw_path)
+ json_data = dict()
+ json_data["image_path"] = "root@127.0.0.1:/home/root/%s" % filename_w_ext
+ json_data["password"] = bmc_pwd
+ json_data["device"] = "cpld"
+ json_data["reboot"] = "no"
+ json_data["type"] = fw_extra_str
+
+ # Call BMC api to install cpld image
+ print("Installing...")
+ r = requests.post(self.fw_upgrade_url, json=json_data)
+ if r.status_code != 200 or 'success' not in r.json().get('result'):
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=invalid cpld image")
+ continue
+
+ cpld_result_list[i] = "DONE"
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "%s upgrade done" % data[1])
+ last_fw_upgrade[3] = ":".join(cpld_result_list)
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "done")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+
+ # Refresh CPLD
+ refresh_img_str_list = []
+ for fw_extra in fw_extra_str_list:
+ if "BASE_CPLD" in fw_extra or "FAN_CPLD" in fw_extra:
+ refresh_img_str_list.append(refresh_img_path)
+ else:
+ refresh_img_str_list.append("None")
+ self.firmware_refresh(None, fw_extra_str_list,
+ ":".join(refresh_img_str_list))
+
+ return True
+
+ elif 'bios' in fw_type:
+ self.__update_fw_upgrade_logger(
+ "bios_upgrade", "start BIOS upgrade")
+ last_fw_upgrade = ["BIOS", fw_path, None, "FAILED"]
+ fw_extra_str = str(fw_extra).lower()
+ flash = fw_extra_str if fw_extra_str in [
+ "master", "slave"] else "master"
+
+ if not os.path.exists(fw_path):
+ self.__update_fw_upgrade_logger(
+ "bios_upgrade", "fail, message=image not found")
+ return False
+
+ scp_command = 'sudo scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -r %s root@240.1.1.1:/home/root/' % os.path.abspath(
+ fw_path)
+ child = pexpect.spawn(scp_command)
+ i = child.expect(["root@240.1.1.1's password:"], timeout=30)
+ if i != 0:
+ self.__update_fw_upgrade_logger(
+ "bios_upgrade", "fail, message=unable to upload image to BMC")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ child.sendline(bmc_pwd)
+ data = child.read()
+ print(data)
+ child.close
+
+ json_data = dict()
+ json_data["data"] = "/usr/bin/ipmitool -b 1 -t 0x2c raw 0x2e 0xdf 0x57 0x01 0x00 0x01"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ self.__update_fw_upgrade_logger(
+ "bios_upgrade", "fail, message=unable to set state")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ filename_w_ext = os.path.basename(fw_path)
+ json_data = dict()
+ json_data["image_path"] = "root@127.0.0.1:/home/root/%s" % filename_w_ext
+ json_data["password"] = bmc_pwd
+ json_data["device"] = "bios"
+ json_data["flash"] = flash
+ json_data["reboot"] = "no"
+
+ print("Installing...")
+ r = requests.post(self.fw_upgrade_url, json=json_data)
+ if r.status_code != 200 or 'success' not in r.json().get('result'):
+ self.__update_fw_upgrade_logger(
+ "bios_upgrade", "fail, message=unable install bios")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ last_fw_upgrade[3] = "DONE"
+ self.__update_fw_upgrade_logger(
+ "bios_upgrade", "done")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ else:
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=invalid firmware type")
+ return False
+
+ return True
+
+ def get_last_upgrade_result(self):
+ """
+ Get last firmware upgrade information, inlcudes:
+ 1) FwType: cpld/fpga/bios/bmc(passed by method 'firmware_upgrade'), string
+ 2) FwPath: path and file name of firmware(passed by method 'firmware_upgrade'), string
+ 3) FwExtra: designated string, econdings of this string is determined by vendor(passed by method 'firmware_program')
+ 4) Result: indicates whether the upgrade action is performed and success/failure status if performed. Values should be one of: "DONE"/"FAILED"/"NOT_PERFORMED".
+ list of object:
+ [
+ {
+ "FwType": "cpld",
+ "FwPath": "cpu_cpld.vme"
+ "FwExtra":"CPU_CPLD"
+ "Result": "DONE"
+ },
+ {
+ "FwType": "cpld",
+ "FwPath": "fan_cpld.vme"
+ "FwExtra": "FAN_CPLD"
+ "Result": "FAILED"
+ }
+ ]
+ """
+ last_update_list = []
+
+ if os.path.exists(self.fw_upgrade_logger_path):
+ with open(self.fw_upgrade_logger_path, 'r') as file:
+ lines = file.read().splitlines()
+
+ upgrade_txt = [i for i in reversed(
+ lines) if "last_upgrade_result" in i]
+ if len(upgrade_txt) > 0:
+ last_upgrade_txt = upgrade_txt[0].split(
+ "last_upgrade_result : ")
+ last_upgrade_list = ast.literal_eval(last_upgrade_txt[1])
+ for x in range(0, len(last_upgrade_list[1].split(":"))):
+ upgrade_dict = {}
+ upgrade_dict["FwType"] = last_upgrade_list[0].lower()
+ upgrade_dict["FwPath"] = last_upgrade_list[1].split(":")[x]
+ upgrade_dict["FwExtra"] = last_upgrade_list[2].split(":")[
+ x] if last_upgrade_list[2] else "None"
+ upgrade_dict["Result"] = last_upgrade_list[3].split(":")[x]
+ last_update_list.append(upgrade_dict)
+
+ return last_update_list
+
+ def firmware_program(self, fw_type, fw_path, fw_extra=None):
+ """
+ Program FPGA and/or CPLD firmware only, but do not refresh them
+
+ @param fw_type value can be: FPGA, CPLD
+ @param fw_path a string of firmware file path, seperated by ':', it should
+ match the sequence of param @fw_type
+ @param fw_extra a string of firmware subtype, i.e CPU_CPLD, BOARD_CPLD,
+ FAN_CPLD, LC_CPLD, etc. Subtypes are seperated by ':'
+ @return True when all required firmware is program succefully,
+ False otherwise.
+
+ Example:
+ self.firmware_program("CPLD", "/cpu_cpld.vme:/lc_cpld", \
+ "CPU_CPLD:LC_CPLD")
+ or
+ self.firmware_program("FPGA", "/fpga.bin")
+ """
+ fw_type = fw_type.lower()
+ bmc_pwd = self.get_bmc_pass()
+ if not bmc_pwd and fw_type != "fpga":
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=BMC credential not found")
+ return False
+
+ if fw_type == 'fpga':
+ last_fw_upgrade = ["FPGA", fw_path, None, "FAILED"]
+ self.__update_fw_upgrade_logger(
+ "fpga_upgrade", "start FPGA upgrade")
+
+ if not os.path.isfile(fw_path):
+ self.__update_fw_upgrade_logger(
+ "fpga_upgrade", "fail, message=FPGA image not found %s" % fw_path)
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ command = 'fpga_prog ' + fw_path
+ print("Running command: %s" % command)
+ process = subprocess.Popen(
+ command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ while True:
+ output = process.stdout.readline()
+ if output == '' and process.poll() is not None:
+ break
+
+ rc = process.returncode
+ if rc != 0:
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=Unable to install FPGA")
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return False
+
+ self.__update_fw_upgrade_logger("fpga_upgrade", "done")
+ last_fw_upgrade[3] = "DONE"
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return True
+
+ elif 'cpld' in fw_type:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "start CPLD upgrade")
+
+ # Check input
+ fw_extra_str = str(fw_extra).upper()
+ if ":" in fw_path and ":" in fw_extra_str:
+ fw_path_list = fw_path.split(":")
+ fw_extra_str_list = fw_extra_str.split(":")
+ else:
+ fw_path_list = [fw_path]
+ fw_extra_str_list = [fw_extra_str]
+
+ if len(fw_path_list) != len(fw_extra_str_list):
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=Invalid input")
+ return False
+
+ cpld_result_list = []
+ data_list = list(zip(fw_path_list, fw_extra_str_list))
+ for data in data_list:
+ fw_path = data[0]
+ fw_extra_str = data[1]
+
+ # Set fw_extra
+ fw_extra_str = {
+ "TOP_LC_CPLD": "top_lc",
+ "BOT_LC_CPLD": "bottom_lc",
+ "FAN_CPLD": "fan",
+ "CPU_CPLD": "cpu",
+ "BASE_CPLD": "base",
+ "COMBO_CPLD": "combo",
+ "SW_CPLD1": "switch",
+ "SW_CPLD2": "switch"
+ }.get(fw_extra_str, None)
+
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "start %s upgrade" % data[1])
+ upgrade_result = "FAILED"
+ for x in range(1, 4):
+ # Set fw_extra
+ if x > 1:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=Retry to upgrade %s" % data[1])
+
+ elif fw_extra_str is None:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=Invalid extra information string %s" % data[1])
+ break
+ elif not os.path.isfile(os.path.abspath(fw_path)):
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=CPLD image not found %s" % fw_path)
+ break
+
+ # Install cpld image via ispvm tool
+ print("Installing...")
+ command = 'ispvm %s' % fw_path
+ if fw_extra_str in ["top_lc", "bottom_lc"]:
+ option = 1 if fw_extra_str == "top_lc" else 2
+ command = "ispvm -c %d %s" % (option,
+ os.path.abspath(fw_path))
+ print("Running command : %s" % command)
+ process = subprocess.Popen(
+ command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ while True:
+ output = process.stdout.readline()
+ if output == '' and process.poll() is not None:
+ break
+
+ rc = process.returncode
+ if rc != 0:
+ self.__update_fw_upgrade_logger(
+ "cpld_upgrade", "fail, message=Unable to install CPLD")
+ continue
+
+ upgrade_result = "DONE"
+ self.__update_fw_upgrade_logger("cpld_upgrade", "done")
+ break
+ cpld_result_list.append(upgrade_result)
+
+ last_fw_upgrade = ["CPLD", ":".join(
+ fw_path_list), ":".join(fw_extra_str_list), ":".join(cpld_result_list)]
+ self.__update_fw_upgrade_logger(
+ "last_upgrade_result", str(last_fw_upgrade))
+ return "FAILED" not in cpld_result_list
+ else:
+ self.__update_fw_upgrade_logger(
+ "fw_upgrade", "fail, message=Invalid firmware type")
+ return False
+
+ return True
+
+ def firmware_refresh(self, fpga_list, cpld_list, fw_extra=None):
+ """
+ Refresh firmware and take extra action when necessary.
+ @param fpga_list a list of FPGA names
+ @param cpld_list a list of CPLD names
+ @return True if refresh succefully and no power cycle action is taken.
+
+ @Note extra action should be: power cycle the whole system(except BMC) when
+ CPU_CPLD or BOARD_CPLD or FPGA is refreshed.
+ No operation if the power cycle is not needed.
+
+ Example:
+ self.firmware_refresh(
+ ["FPGA"], ["BASE_CPLD", "LC_CPLD"],"/tmp/fw/refresh.vme")
+ or
+ self.firmware_refresh(["FPGA"], None, None)
+ or
+ self.firmware_refresh(None, ["FAN_CPLD", "LC1_CPLD", "BASE_CPLD"],
+ "/tmp/fw/fan_refresh.vme:none:/tmp/fw/base_refresh.vme")
+ """
+
+ if not fpga_list and not cpld_list:
+ return False
+
+ if type(cpld_list) is list and ("BASE_CPLD" in cpld_list or "FAN_CPLD" in cpld_list):
+ refresh_list = fpga_list + \
+ cpld_list if type(fpga_list) is list else cpld_list
+ self.__update_fw_upgrade_logger(
+ "fw_refresh", "start %s refresh" % ",".join(refresh_list))
+ fw_path_list = fw_extra.split(':')
+ command = "echo "
+ if len(fw_path_list) != len(cpld_list):
+ self.__update_fw_upgrade_logger(
+ "cpld_refresh", "fail, message=Invalid fw_extra")
+ return False
+
+ for idx in range(0, len(cpld_list)):
+ fw_path = fw_path_list[idx]
+ refresh_type = {
+ "BASE_CPLD": "base",
+ "FAN_CPLD": "fan"
+ }.get(cpld_list[idx], None)
+
+ if not refresh_type:
+ continue
+ elif not self.upload_file_bmc(fw_path):
+ self.__update_fw_upgrade_logger(
+ "cpld_refresh", "fail, message=Unable to upload refresh image to BMC")
+ return False
+ else:
+ filename_w_ext = os.path.basename(fw_path)
+
+ sub_command = "%s /home/root/%s > /tmp/cpld_refresh " % (
+ refresh_type, filename_w_ext)
+ command += sub_command
+
+ json_data = dict()
+ json_data["data"] = command
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ self.__update_fw_upgrade_logger(
+ "cpld_refresh", "fail, message=%d Invalid refresh image" % r.status_code)
+ return False
+ elif type(cpld_list) is list:
+ refresh_list = fpga_list + \
+ cpld_list if type(fpga_list) is list else cpld_list
+ self.__update_fw_upgrade_logger(
+ "fw_refresh", "start %s refresh" % ",".join(refresh_list))
+ json_data = dict()
+ json_data["data"] = "echo cpu_cpld > /tmp/cpld_refresh"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ self.__update_fw_upgrade_logger(
+ "cpld_refresh", "fail, message=%d Unable to load new CPLD" % r.status_code)
+ return False
+ elif type(fpga_list) is list:
+ self.__update_fw_upgrade_logger(
+ "fw_refresh", "start FPGA refresh")
+ json_data = dict()
+ json_data["data"] = "echo fpga > /tmp/cpld_refresh"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ self.__update_fw_upgrade_logger(
+ "cpld_refresh", "fail, message=%d Unable to load new FPGA" % r.status_code)
+ return False
+ else:
+ self.__update_fw_upgrade_logger(
+ "fw_refresh", "fail, message=Invalid input")
+ return False
+
+ self.__update_fw_upgrade_logger("fw_refresh", "done")
+ return True
+
+ def get_running_bmc(self):
+ """
+ Get booting flash of running BMC.
+ @return a string, "master" or "slave"
+ """
+ json_data = dict()
+ json_data["data"] = "/usr/local/bin/boot_info.sh"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ try:
+ boot_info_list = r.json().get('result')
+ for boot_info_raw in boot_info_list:
+ boot_info = boot_info_raw.split(":")
+ if "Current Boot Code Source" in boot_info[0]:
+ flash = "master" if "master "in boot_info[1].lower(
+ ) else "slave"
+ return flash
+ raise Exception(
+ "Error: Unable to detect booting flash of running BMC")
+ except Exception as e:
+ raise Exception(e)
+
+ def set_bmc_boot_flash(self, flash):
+ """
+ Set booting flash of BMC
+ @param flash should be "master" or "slave"
+ """
+ if flash.lower() not in ["master", "slave"]:
+ return False
+ json_data = dict()
+ json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;bmc_reboot %s" % flash
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ return False
+ return True
+
+ def reboot_bmc(self):
+ """
+ Reboot BMC
+ """
+ json_data = dict()
+ json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;bmc_reboot reboot"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ return False
+ return True
+
+ def get_current_bios(self):
+ """
+ # Get booting bios image of current running host OS
+ # @return a string, "master" or "slave"
+ """
+ json_data = dict()
+ json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;come_boot_info"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ try:
+ cpu_boot_info_list = r.json().get('result')
+ for cpu_boot_info_raw in cpu_boot_info_list:
+ if "COMe CPU boots from BIOS" in cpu_boot_info_raw:
+ bios_image = "master" if "master "in cpu_boot_info_raw.lower(
+ ) else "slave"
+ return bios_image
+ raise Exception(
+ "Error: Unable to detect current running bios image")
+ except Exception as e:
+ raise Exception(e)
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/optictemputil.py b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/optictemputil.py
new file mode 100644
index 000000000000..0e5b6a1c7109
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/optictemputil.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+
+#
+# optictemputil.py
+#
+# Platform-specific Optic module temperature Interface for SONiC
+#
+
+__author__ = 'Pradchaya P.'
+__author__ = 'Wirut G.'
+__license__ = "GPL"
+__version__ = "1.0.0"
+__status__ = "Development"
+
+import os
+import sys
+import binascii
+import subprocess
+
+class OpticTempUtil():
+ """Platform-specific OpticTempUtil class"""
+
+ def __init__(self):
+ pass
+
+ def read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes):
+ eeprom_raw = []
+ for i in range(0, num_bytes):
+ eeprom_raw.append("0x00")
+
+ try:
+ sysfsfile_eeprom.seek(offset)
+ raw = sysfsfile_eeprom.read(num_bytes)
+ except IOError:
+ return None
+
+ try:
+ for n in range(0, num_bytes):
+ eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
+ except:
+ return None
+
+ return eeprom_raw
+
+
+ def twos_comp(self, num, bits):
+ try:
+ if ((num & (1 << (bits - 1))) != 0):
+ num = num - (1 << bits)
+ return num
+ except:
+ return 0
+
+
+ def calc_temperature(self, cal_type, eeprom_data, offset, size):
+
+ msb = int(eeprom_data[offset], 16)
+ lsb = int(eeprom_data[offset + 1], 16)
+
+ result = (msb << 8) | (lsb & 0xff)
+ result = self.twos_comp(result, 16)
+
+ if cal_type == 1:
+ # Internal calibration
+ result = float(result / 256.0)
+ retval = '%.4f' %result
+
+ # TODO: Should support external calibration in future.
+ else:
+ retval = 0
+
+ return retval
+
+ ''' TODO: Change busnum to sysfs_sfp_i2c_client_eeprom_path from caller!!!
+ '''
+ def get_optic_temp(self, sysfs_sfp_i2c_client_eeprom_path, port_type):
+
+ EEPROM_ADDR = 0x50
+ DOM_ADDR = 0x51
+ EEPROM_OFFSET = 0
+ DOM_OFFSET = 256
+
+ SFP_DMT_ADDR = 92
+ SFP_DMT_WIDTH = 1
+ SFP_TEMP_DATA_ADDR = 96
+ SFP_TEMP_DATA_WIDTH = 2
+
+ QSFP_TEMP_DATA_ADDR = 22
+ QSFP_TEMP_DATA_WIDTH = 2
+ temperature_raw = None
+
+
+ ''' Open file here '''
+ try:
+ sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0)
+ except IOError:
+ print("Error: reading sysfs file %s" % sysfs_sfp_i2c_client_eeprom_path)
+ return 0
+
+ if port_type == 'QSFP':
+
+ # QSFP only have internal calibration mode.
+ cal_type = 1
+ # read temperature raw value
+ temperature_raw = self.read_eeprom_specific_bytes(sysfsfile_eeprom,(EEPROM_OFFSET+QSFP_TEMP_DATA_ADDR),QSFP_TEMP_DATA_WIDTH)
+ else:
+ # read calibration type at bit 5
+ cal_type = self.read_eeprom_specific_bytes(sysfsfile_eeprom,EEPROM_OFFSET+SFP_DMT_ADDR,SFP_DMT_WIDTH)
+ if cal_type is None:
+ return 0
+ else:
+ cal_type = (int(cal_type[0],16) >> 5 ) & 1
+ # read temperature raw value
+ temperature_raw = self.read_eeprom_specific_bytes(sysfsfile_eeprom,(DOM_OFFSET+SFP_TEMP_DATA_ADDR),SFP_TEMP_DATA_WIDTH)
+
+ try:
+ sysfsfile_eeprom.close()
+ except IOError:
+ print("Error: closing sysfs file %s" % file_path)
+ return 0
+
+ #calculate temperature
+ if temperature_raw is not None:
+ return self.calc_temperature(cal_type, temperature_raw, 0, 2)
+ else:
+ return 0
\ No newline at end of file
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/optictemputil_lp.py b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/optictemputil_lp.py
new file mode 100644
index 000000000000..0e5b6a1c7109
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/optictemputil_lp.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+
+#
+# optictemputil.py
+#
+# Platform-specific Optic module temperature Interface for SONiC
+#
+
+__author__ = 'Pradchaya P.'
+__author__ = 'Wirut G.'
+__license__ = "GPL"
+__version__ = "1.0.0"
+__status__ = "Development"
+
+import os
+import sys
+import binascii
+import subprocess
+
+class OpticTempUtil():
+ """Platform-specific OpticTempUtil class"""
+
+ def __init__(self):
+ pass
+
+ def read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes):
+ eeprom_raw = []
+ for i in range(0, num_bytes):
+ eeprom_raw.append("0x00")
+
+ try:
+ sysfsfile_eeprom.seek(offset)
+ raw = sysfsfile_eeprom.read(num_bytes)
+ except IOError:
+ return None
+
+ try:
+ for n in range(0, num_bytes):
+ eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
+ except:
+ return None
+
+ return eeprom_raw
+
+
+ def twos_comp(self, num, bits):
+ try:
+ if ((num & (1 << (bits - 1))) != 0):
+ num = num - (1 << bits)
+ return num
+ except:
+ return 0
+
+
+ def calc_temperature(self, cal_type, eeprom_data, offset, size):
+
+ msb = int(eeprom_data[offset], 16)
+ lsb = int(eeprom_data[offset + 1], 16)
+
+ result = (msb << 8) | (lsb & 0xff)
+ result = self.twos_comp(result, 16)
+
+ if cal_type == 1:
+ # Internal calibration
+ result = float(result / 256.0)
+ retval = '%.4f' %result
+
+ # TODO: Should support external calibration in future.
+ else:
+ retval = 0
+
+ return retval
+
+ ''' TODO: Change busnum to sysfs_sfp_i2c_client_eeprom_path from caller!!!
+ '''
+ def get_optic_temp(self, sysfs_sfp_i2c_client_eeprom_path, port_type):
+
+ EEPROM_ADDR = 0x50
+ DOM_ADDR = 0x51
+ EEPROM_OFFSET = 0
+ DOM_OFFSET = 256
+
+ SFP_DMT_ADDR = 92
+ SFP_DMT_WIDTH = 1
+ SFP_TEMP_DATA_ADDR = 96
+ SFP_TEMP_DATA_WIDTH = 2
+
+ QSFP_TEMP_DATA_ADDR = 22
+ QSFP_TEMP_DATA_WIDTH = 2
+ temperature_raw = None
+
+
+ ''' Open file here '''
+ try:
+ sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0)
+ except IOError:
+ print("Error: reading sysfs file %s" % sysfs_sfp_i2c_client_eeprom_path)
+ return 0
+
+ if port_type == 'QSFP':
+
+ # QSFP only have internal calibration mode.
+ cal_type = 1
+ # read temperature raw value
+ temperature_raw = self.read_eeprom_specific_bytes(sysfsfile_eeprom,(EEPROM_OFFSET+QSFP_TEMP_DATA_ADDR),QSFP_TEMP_DATA_WIDTH)
+ else:
+ # read calibration type at bit 5
+ cal_type = self.read_eeprom_specific_bytes(sysfsfile_eeprom,EEPROM_OFFSET+SFP_DMT_ADDR,SFP_DMT_WIDTH)
+ if cal_type is None:
+ return 0
+ else:
+ cal_type = (int(cal_type[0],16) >> 5 ) & 1
+ # read temperature raw value
+ temperature_raw = self.read_eeprom_specific_bytes(sysfsfile_eeprom,(DOM_OFFSET+SFP_TEMP_DATA_ADDR),SFP_TEMP_DATA_WIDTH)
+
+ try:
+ sysfsfile_eeprom.close()
+ except IOError:
+ print("Error: closing sysfs file %s" % file_path)
+ return 0
+
+ #calculate temperature
+ if temperature_raw is not None:
+ return self.calc_temperature(cal_type, temperature_raw, 0, 2)
+ else:
+ return 0
\ No newline at end of file
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/optictemputil_rl.py b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/optictemputil_rl.py
new file mode 100644
index 000000000000..9f679799aeec
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/optictemputil_rl.py
@@ -0,0 +1,133 @@
+#!/usr/bin/env python
+
+#
+# optictemputil.py
+#
+# Platform-specific Optic module temperature Interface for SONiC
+#
+
+__author__ = 'Pradchaya P.'
+__author__ = 'Wirut G.'
+__license__ = "GPL"
+__version__ = "1.0.0"
+__status__ = "Development"
+
+import os
+import sys
+import binascii
+import subprocess
+
+class OpticTempUtil():
+ """Platform-specific OpticTempUtil class"""
+
+ def __init__(self):
+ pass
+
+ def read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes):
+ eeprom_raw = []
+ for i in range(0, num_bytes):
+ eeprom_raw.append("0x00")
+
+ try:
+ sysfsfile_eeprom.seek(offset)
+ raw = sysfsfile_eeprom.read(num_bytes)
+ except IOError:
+ return None
+
+ try:
+ for n in range(0, num_bytes):
+ eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
+ except:
+ return None
+
+ return eeprom_raw
+
+
+ def twos_comp(self, num, bits):
+ try:
+ if ((num & (1 << (bits - 1))) != 0):
+ num = num - (1 << bits)
+ return num
+ except:
+ return 0
+
+
+ def calc_temperature(self, cal_type, eeprom_data, offset, size):
+
+ msb = int(eeprom_data[offset], 16)
+ lsb = int(eeprom_data[offset + 1], 16)
+
+ thousand_digit_int = (msb >> 4) & 0x0f
+ hundred_digit_int = msb & 0x0f
+ tens_digit_int = (lsb >> 4) & 0x0f
+ single_digit_int = lsb & 0x0f
+
+ result = thousand_digit_int * 16 * 16 * 16 + hundred_digit_int * 16 * 16 +
+ tens_digit_int * 16 + single_digit_int
+
+ #result = self.twos_comp(result, 16)
+
+ if cal_type == 1:
+ # Internal calibration
+ result = float(result / 256.0)
+ retval = '%.4f' %result
+
+ # TODO: Should support external calibration in future.
+ else:
+ retval = 0
+
+ return retval
+
+ ''' TODO: Change busnum to sysfs_sfp_i2c_client_eeprom_path from caller!!!
+ '''
+ def get_optic_temp(self, sysfs_sfp_i2c_client_eeprom_path, port_type):
+
+ EEPROM_ADDR = 0x50
+ DOM_ADDR = 0x51
+ EEPROM_OFFSET = 0
+ DOM_OFFSET = 256
+
+ SFP_DMT_ADDR = 92
+ SFP_DMT_WIDTH = 1
+ SFP_TEMP_DATA_ADDR = 96
+ SFP_TEMP_DATA_WIDTH = 2
+
+ QSFP_TEMP_DATA_ADDR = 14
+ QSFP_TEMP_DATA_WIDTH = 2
+ temperature_raw = None
+
+
+ ''' Open file here '''
+ try:
+ sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0)
+ except IOError:
+ print("Error: reading sysfs file %s" % sysfs_sfp_i2c_client_eeprom_path)
+ return 0
+
+ if port_type == 'QSFP':
+
+ # QSFP only have internal calibration mode.
+ cal_type = 1
+ # read temperature raw value
+ temperature_raw = self.read_eeprom_specific_bytes(sysfsfile_eeprom,(EEPROM_OFFSET+QSFP_TEMP_DATA_ADDR),QSFP_TEMP_DATA_WIDTH)
+ else:
+ # read calibration type at bit 5
+ cal_type = self.read_eeprom_specific_bytes(sysfsfile_eeprom,EEPROM_OFFSET+SFP_DMT_ADDR,SFP_DMT_WIDTH)
+ if cal_type is None:
+ return 0
+ else:
+ cal_type = (int(cal_type[0],16) >> 5 ) & 1
+ # read temperature raw value
+ temperature_raw = self.read_eeprom_specific_bytes(sysfsfile_eeprom,(DOM_OFFSET+SFP_TEMP_DATA_ADDR),SFP_TEMP_DATA_WIDTH)
+
+ try:
+ sysfsfile_eeprom.close()
+ except IOError:
+ print("Error: closing sysfs file %s" % file_path)
+ return 0
+
+ #calculate temperature
+ if temperature_raw is not None:
+ return self.calc_temperature(cal_type, temperature_raw, 0, 2)
+ else:
+ return 0
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/psuutil.py b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/psuutil.py
new file mode 100644
index 000000000000..d3a27117f5a2
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/psuutil.py
@@ -0,0 +1,248 @@
+#!/usr/bin/env python
+
+__author__ = 'Wirut G.'
+__license__ = "GPL"
+__version__ = "0.1.4"
+__status__ = "Development"
+
+import requests
+import re
+
+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.fru_status_url = "http://240.1.1.1:8080/api/sys/fruid/status"
+ self.psu_info_url = "http://240.1.1.1:8080/api/sys/fruid/psu"
+
+ self.fru_status_list = None
+ self.psu_info_list = None
+
+ def request_data(self):
+ # Reqest data from BMC if not exist.
+ if self.fru_status_list is None or self.psu_info_list is None:
+ fru_status_req = requests.get(self.fru_status_url)
+ psu_info_req = requests.get(self.psu_info_url)
+ fru_status_json = fru_status_req.json()
+ psu_info_json = psu_info_req.json()
+ self.fru_status_list = fru_status_json.get('Information')
+ self.psu_info_list = psu_info_json.get('Information')
+ return self.fru_status_list, self.psu_info_list
+
+ def airflow_selector(self, pn):
+ # Set airflow type
+ pn = pn.upper()
+ if "DPS-1100FB" in pn:
+ airflow = "FTOB"
+ elif "DPS-1100AB" in pn:
+ airflow = "BTOF"
+ elif "FSJ026-A20G" in pn:
+ airflow = "FTOB"
+ elif "FSJ038-A20G" in pn:
+ airflow = "BTOF"
+ else:
+ airflow = "Unknown"
+ return airflow
+
+ 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
+ """
+
+ num_psus = 2
+
+ return num_psus
+
+ 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
+ """
+
+ # init data
+ psu_key = "PSU" + str(index)
+ psu_status_key = "Power Status"
+ psu_power_status = False
+
+ try:
+ # Request and validate sensor's information
+ self.fru_status_list, self.psu_info_list = self.request_data()
+
+ # Get PSU power status.
+ for fru_status in self.fru_status_list:
+ is_psu = fru_status.get(psu_key)
+ psu_status = str(fru_status.get(psu_status_key)).strip()
+
+ if is_psu is not None and psu_status == "OK":
+ psu_power_status = True
+
+ except:
+ print("Error: Unable to access PSU power status")
+ return False
+
+ return psu_power_status
+
+ 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
+ """
+
+ # Init data
+ psu_key = "PSU" + str(index)
+ psu_presence_key = "Present"
+ psu_presence_status = False
+
+ try:
+ # Request and validate sensor's information.
+ self.fru_status_list, self.psu_info_list = self.request_data()
+
+ # Get PSU present status.
+ for fru_status in self.fru_status_list:
+ is_psu = fru_status.get(psu_key)
+ psu_status = str(fru_status.get(psu_presence_key)).strip()
+
+ if is_psu is not None and psu_status == "Present":
+ psu_presence_status = True
+
+ except:
+ print("Error: Unable to access PSU presence status")
+ return False
+
+ return psu_presence_status
+
+ def get_psu_sn(self, index):
+ """
+ Get the serial number of the psu,
+
+ :param index: An integer, 1-based index of the PSU.
+ :return: Serial number
+ """
+ serial_number = "N/A"
+ psu_key = "PSU" + str(index) + " FRU"
+ psu_sn_key = "Serial Number"
+
+ try:
+ # Request and validate sensor's information.
+ self.fru_status_list, self.psu_info_list = self.request_data()
+
+ # Get PSU fru info.
+ for psu_fru in self.psu_info_list:
+ psu_sn = str(psu_fru.get(psu_sn_key)).strip()
+ if psu_fru.get(psu_key) is not None:
+ serial_number = psu_sn if psu_sn.strip() != "" else "N/A"
+ break
+
+ except:
+ return "N/A"
+
+ return serial_number
+
+ def get_psu_pn(self, index):
+ """
+ Get the product name of the psu
+
+ :param index: An integer, 1-based index of the PSU.
+ :return: Product name
+ """
+ product_name = "N/A"
+ psu_key = "PSU" + str(index) + " FRU"
+ psu_pn_key = "Product Name"
+
+ try:
+ # Request and validate sensor's information
+ self.fru_status_list, self.psu_info_list = self.request_data()
+
+ # Get PSU fru info.
+ for psu_fru in self.psu_info_list:
+ psu_pn = str(psu_fru.get(psu_pn_key)).strip()
+ if psu_fru.get(psu_key) is not None:
+ product_name = psu_pn if psu_pn.strip() != "" else "N/A"
+ break
+
+ except:
+ return "N/A"
+
+ return product_name
+
+ def get_all(self):
+ """
+ Number: mandatory, max number of PSU, integer
+ PSU1, PSU2, ...: mandatory, PSU name, string
+ Present: mandatory for each PSU, present status, boolean, True for present, False for NOT present
+ PowerStatus: conditional, if PRESENT is True, power status of PSU,boolean, True for powered, False for NOT powered
+ PN, conditional, if PRESENT is True, PN of the PSU, string
+ SN, conditional, if PRESENT is True, SN of the PSU, string
+ """
+
+ # Init data
+ all_psu_dict = dict()
+ all_psu_dict["Number"] = self.get_num_psus()
+ psu_sn_key_1 = "Serial Number"
+ psu_sn_key_2 = "Product Serial"
+ psu_pn_key = "Product Name"
+
+ # Request and validate sensor's information.
+ self.fru_status_list, self.psu_info_list = self.request_data()
+
+ # Set PSU FRU data.
+ psu_info_dict = dict()
+ for psu_fru in self.psu_info_list:
+ psu_data = dict()
+ pn = psu_fru.get(psu_pn_key)
+ sn = psu_fru.get(psu_sn_key_1) or psu_fru.get(psu_sn_key_2)
+ psu_data["PN"] = "N/A" if not pn or str(
+ pn).strip() == "" else str(pn).strip()
+ psu_data["SN"] = "N/A" if not pn or str(
+ pn).strip() == "" else str(sn).strip()
+
+ fru_check = [psu_fru[v] for v in psu_fru.keys() if 'FRU Info' in v]
+ non_fru_check = [v for v in psu_fru.keys() if 'PSU' in v]
+
+ if len(non_fru_check) > 0:
+ psu_idx = int(re.findall('\d+', non_fru_check[0])[0])
+ psu_info_dict[psu_idx] = psu_data
+ elif len(fru_check) > 0:
+ psu_idx = int(re.findall('\d+', fru_check[0])[0])
+ psu_info_dict[psu_idx] = psu_data
+
+ # Set PSU status.
+ for fru_status in self.fru_status_list:
+ psu_status_dict = dict()
+ find_psu = [v for v in fru_status.keys() if "PSU" in v]
+ if len(find_psu) > 0:
+ psu_idx = int(re.findall('\d+', find_psu[0])[0])
+ psu_ps_status = True if str(fru_status.get(
+ "Present")).strip() == "Present" else False
+ psu_pw_status = True if str(fru_status.get(
+ "Power Status")).strip() == "OK" else False
+ psu_pw_type = str(fru_status.get(
+ "Power Type")).strip()
+ ac_status = True if str(fru_status.get(
+ "AC Status")).strip().upper() == "OK" else False
+
+ psu_status_dict["Present"] = psu_ps_status
+ if psu_ps_status:
+ psu_status_dict["PowerStatus"] = psu_pw_status
+ psu_status_dict["PN"] = psu_info_dict[psu_idx]["PN"]
+ psu_status_dict["SN"] = psu_info_dict[psu_idx]["SN"]
+ psu_status_dict["InputType"] = psu_pw_type
+ psu_status_dict["InputStatus"] = True if psu_pw_status and psu_ps_status else False
+ psu_status_dict["OutputStatus"] = ac_status
+ psu_status_dict["AirFlow"] = self.airflow_selector(
+ psu_status_dict["PN"])
+ all_psu_dict[find_psu[0]] = psu_status_dict
+
+ return all_psu_dict
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/sensorutil.py b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/sensorutil.py
new file mode 100644
index 000000000000..796949126ccc
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/sensorutil.py
@@ -0,0 +1,369 @@
+#!/usr/bin/env python
+
+__author__ = 'Wirut G.'
+__license__ = "GPL"
+__version__ = "0.2.0"
+__status__ = "Development"
+
+import requests
+
+
+class SensorUtil():
+ """Platform-specific SensorUtil class"""
+
+ def __init__(self):
+ self.sensor_url = "http://240.1.1.1:8080/api/sys/sensors"
+ self.sys_fruid_url = "http://240.1.1.1:8080/api/sys/fruid/sys"
+ self.sensor_info_list = None
+
+ def request_data(self):
+ # Reqest data from BMC if not exist.
+ if self.sensor_info_list is None:
+ sensor_data_req = requests.get(self.sensor_url)
+ sensor_json = sensor_data_req.json()
+ self.sensor_info_list = sensor_json.get('Information')
+ sys_fruid_req = requests.get(self.sys_fruid_url)
+ sys_fruid_json = sys_fruid_req.json()
+ self.sys_fruid_list = sys_fruid_json.get('Information')
+ return self.sensor_info_list
+
+ def input_type_selector(self, unit):
+ # Set input type.
+ return {
+ "C": "temperature",
+ "V": "voltage",
+ "RPM": "RPM",
+ "A": "amp",
+ "W": "power"
+ }.get(unit, unit)
+
+ def input_name_selector(self, sensor_name, input_name):
+
+ self.sensor_name = {
+ "syscpld-i2c-0-0d": "TEMPERATURE",
+ "dps1100-i2c-24-58": "PSU1",
+ "dps1100-i2c-25-59": "PSU2",
+ "fancpld-i2c-8-0d": "FAN"
+ }.get(sensor_name, sensor_name)
+
+ if 'dps1100' in sensor_name:
+ input_name = {
+ "fan1": self.sensor_name + "_FAN",
+ "iin": self.sensor_name + "_CURR_I",
+ "iout1": self.sensor_name + "_CURR_O",
+ "pin": self.sensor_name + "_POWER_I",
+ "pout1": self.sensor_name + "_POWER_O",
+ "temp1": self.sensor_name + "_TEMP1",
+ "temp2": self.sensor_name + "_TEMP2",
+ "vin": self.sensor_name + "_VOL_I",
+ "vout1": self.sensor_name + "_VOL_O"
+ }.get(input_name, input_name)
+
+ elif 'tmp75' in sensor_name:
+ input_name = {
+ "tmp75-i2c-7-4d": "FTB_INLET_RIGHT",
+ "tmp75-i2c-7-4c": "FTB_INLET_LEFT",
+ "tmp75-i2c-7-4b": "FTB_SWITCH_OUTLET",
+ "tmp75-i2c-7-4a": "BTF_SWITCH_OUTLET",
+ "tmp75-i2c-39-48": "BTF_INLET_RIGHT",
+ "tmp75-i2c-39-49": "BTF_INLET_LEFT"
+ }.get(sensor_name, input_name)
+ if self.get_sys_airflow() == "FTOB" and sensor_name == "tmp75-i2c-7-4d":
+ input_name = "INLET_TEMP"
+
+ if self.get_sys_airflow() == "BTOF" and sensor_name == "tmp75-i2c-39-48":
+ input_name = "INLET_TEMP"
+
+ self.sensor_name = "TEMPERATURE"
+
+ elif 'fancpld' in sensor_name:
+ raw_fan_input = input_name.split()
+ input_name = raw_fan_input[0] + \
+ raw_fan_input[1] + "_" + raw_fan_input[2]
+
+ elif 'ir35' in sensor_name or 'ir38' in sensor_name:
+ sensor_name_raw = sensor_name.split("-")
+ sensor_name = sensor_name_raw[0]
+ self.sensor_name = sensor_name.upper()
+
+ return input_name.replace(" ", "_").upper()
+
+ def get_num_sensors(self):
+ """
+ Get the number of sensors
+ :return: int num_sensors
+ """
+
+ num_sensors = 0
+ try:
+ # Request and validate sensor's information
+ self.sensor_info_list = self.request_data()
+
+ # Get number of sensors.
+ num_sensors = len(self.sensor_info_list)
+ except:
+ print "Error: Unable to access sensor information"
+ return 0
+
+ return num_sensors
+
+ def get_sensor_input_num(self, index):
+ """
+ Get the number of the input items of the specified sensor
+ :return: int input_num
+ """
+
+ input_num = 0
+ try:
+ # Request and validate sensor's information.
+ self.sensor_info_list = self.request_data()
+
+ # Get sensor's input number.
+ sensor_data = self.sensor_info_list[index-1]
+ input_num = len(sensor_data.keys())-2
+ except:
+ print "Error: Unable to access sensor information"
+ return 0
+
+ return input_num
+
+ def get_sensor_name(self, index):
+ """
+ Get the device name of the specified sensor.
+ for example "coretemp-isa-0000"
+ :return: str sensor_name
+ """
+
+ sensor_name = "N/A"
+ try:
+ # Request and validate sensor's information.
+ self.sensor_info_list = self.request_data()
+
+ # Get sensor's name.
+ sensor_data = self.sensor_info_list[index-1]
+ sensor_name = sensor_data.get('name')
+
+ except:
+ return "N/A"
+
+ return sensor_name
+
+ def get_sensor_input_name(self, sensor_index, input_index):
+ """
+ Get the input item name of the specified input item of the
+ specified sensor index, for example "Physical id 0"
+ :return: str sensor_input_name
+ """
+
+ sensor_input_name = "N/A"
+ try:
+ # Request and validate sensor's information.
+ self.sensor_info_list = self.request_data()
+ sensor_data = self.sensor_info_list[sensor_index-1].copy()
+
+ # Remove none input key.
+ del sensor_data["name"]
+ del sensor_data["Adapter"]
+
+ # Get sensor's input name.
+ sensor_data_key = sensor_data.keys()
+ sensor_input_name = sensor_data_key[input_index-1]
+ except:
+ return "N/A"
+
+ return sensor_input_name
+
+ def get_sensor_input_type(self, sensor_index, input_index):
+ """
+ Get the item type of the specified input item of the specified sensor index,
+ The return value should among "valtage","temperature"
+ :return: str sensor_input_type
+ """
+
+ sensor_input_type = "N/A"
+ try:
+ # Request and validate sensor's information.
+ self.sensor_info_list = self.request_data()
+ sensor_data = self.sensor_info_list[sensor_index-1].copy()
+
+ # Remove none input key.
+ del sensor_data["name"]
+ del sensor_data["Adapter"]
+
+ # Get sensor's input type name.
+ sensor_data_key = sensor_data.keys()
+ sensor_input_raw = sensor_data.get(sensor_data_key[input_index-1])
+ sensor_data_str = sensor_input_raw.split()
+ sensor_input_type = self.input_type_selector(sensor_data_str[1])
+ except:
+ return "N/A"
+
+ return sensor_input_type
+
+ def get_sensor_input_value(self, sensor_index, input_index):
+ """
+ Get the current value of the input item, the unit is "V" or "C"
+ :return: float sensor_input_value
+ """
+
+ sensor_input_value = 0
+ try:
+ # Request and validate sensor's information.
+ self.sensor_info_list = self.request_data()
+ sensor_data = self.sensor_info_list[sensor_index-1].copy()
+
+ # Remove none input key.
+ del sensor_data["name"]
+ del sensor_data["Adapter"]
+
+ # Get sensor's input value.
+ sensor_data_key = sensor_data.keys()
+ sensor_input_raw = sensor_data.get(sensor_data_key[input_index-1])
+ sensor_data_str = sensor_input_raw.split()
+ sensor_input_value = float(
+ sensor_data_str[0]) if sensor_data_str[0] != "N/A" else 0
+ except:
+ print "Error: Unable to access sensor information"
+ return 0
+
+ return sensor_input_value
+
+ def get_sensor_input_low_threshold(self, sensor_index, input_index):
+ """
+ Get the low threshold of the value,
+ the status of this item is not ok if the current value 1:
+ sensor_input_low_threshold = l_thres * \
+ 1000 if str(unit[0]).lower() == 'k' else l_thres
+ except:
+ print "Error: Unable to access sensor information"
+ return 0
+
+ return sensor_input_low_threshold
+
+ def get_sensor_input_high_threshold(self, sensor_index, input_index):
+ """
+ Get the high threshold of the value,
+ the status of this item is not ok if the current value > high_threshold
+ :return: float sensor_input_high_threshold
+ """
+
+ sensor_input_high_threshold = 0
+ try:
+ # Request and validate sensor's information.
+ self.sensor_info_list = self.request_data()
+ sensor_data = self.sensor_info_list[sensor_index-1].copy()
+
+ # Remove none input key.
+ del sensor_data["name"]
+ del sensor_data["Adapter"]
+
+ # Get sensor's input high threshold.
+ sensor_data_key = sensor_data.keys()
+ sensor_input_raw = sensor_data.get(sensor_data_key[input_index-1])
+ sensor_data_str = sensor_input_raw.split()
+ indices = [i for i, s in enumerate(
+ sensor_data_str) if 'max' in s or 'high' in s]
+ h_thres = float(
+ sensor_data_str[indices[0] + 2]) if len(indices) != 0 else 0
+ unit = sensor_data_str[indices[0] +
+ 3] if len(indices) != 0 else None
+ if unit is not None and len(unit) > 1:
+ sensor_input_high_threshold = h_thres * \
+ 1000 if str(unit[0]).lower() == 'k' else h_thres
+
+ except:
+ print "Error: Unable to access sensor information"
+ return 0
+
+ return sensor_input_high_threshold
+
+ def get_sys_airflow(self):
+ sys_air_flow = "Unknown"
+ sys_pn_data = [
+ v.split(":") for v in self.sys_fruid_list if "Product Part Number" in v]
+
+ if len(sys_pn_data) == 0:
+ return sys_air_flow
+
+ sys_pn = sys_pn_data[0][1]
+ if "R1241-F0001" in sys_pn:
+ sys_air_flow = "FTOB"
+ elif"R1241-F0002" in sys_pn:
+ sys_air_flow = "BTOF"
+
+ return sys_air_flow
+
+ def get_all(self):
+
+ all_sensor_dict = dict()
+
+ # Request sensor's information.
+ self.sensor_info_list = self.request_data()
+ for sensor_data in self.sensor_info_list:
+ sensor_info = sensor_data.copy()
+
+ # Remove none unuse key.
+ del sensor_info["name"]
+ del sensor_info["Adapter"]
+
+ # Set sensor data.
+ sensor_dict = dict()
+ for k, v in sensor_info.items():
+ sensor_i_dict = dict()
+ sensor_data_str = v.split()
+ indices_h = [i for i, s in enumerate(
+ sensor_data_str) if 'max' in s or 'high' in s]
+ indices_l = [i for i, s in enumerate(
+ sensor_data_str) if 'min' in s or 'low' in s]
+ h_thres = float(
+ sensor_data_str[indices_h[0] + 2]) if len(indices_h) != 0 else 0
+ l_thres = float(
+ sensor_data_str[indices_l[0] + 2]) if len(indices_l) != 0 else 0
+ thres_unit = sensor_data_str[-1]
+
+ sensor_i_dict["Type"] = self.input_type_selector(
+ sensor_data_str[1])
+ sensor_i_dict["Value"] = float(
+ sensor_data_str[0]) if sensor_data_str[0] != "N/A" else 0
+ sensor_i_dict["HighThd"] = h_thres * \
+ 1000 if str(thres_unit[0]).lower() == 'k' else h_thres
+ sensor_i_dict["LowThd"] = l_thres * \
+ 1000 if str(thres_unit[0]).lower() == 'k' else l_thres
+
+ k = self.input_name_selector(sensor_data.get('name'), k)
+ sensor_dict[k] = sensor_i_dict
+
+ if all_sensor_dict.get(self.sensor_name) is None:
+ all_sensor_dict[self.sensor_name] = dict()
+
+ all_sensor_dict[self.sensor_name].update(sensor_dict)
+
+ sensor_dict = dict()
+ sensor_dict["Sys_AirFlow"] = self.get_sys_airflow()
+ all_sensor_dict["TEMPERATURE"].update(sensor_dict)
+
+ return all_sensor_dict
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/sfputil.py b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/sfputil.py
new file mode 100755
index 000000000000..f0187acb4eb6
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/plugins/sfputil.py
@@ -0,0 +1,234 @@
+#!/usr/bin/env python
+#
+# Platform-specific SFP transceiver interface for SONiC
+#
+
+try:
+ import time
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
+
+
+class SfpUtil(SfpUtilBase):
+ """Platform-specific SfpUtil class"""
+
+ PORT_START = 1
+ PORT_END = 40
+ QSFP_PORT_START = 1
+ QSFP_PORT_END = 40
+
+ EEPROM_OFFSET = 9
+ PORT_INFO_PATH = '/sys/class/fishbone2_fpga'
+
+ _port_name = ""
+ _port_to_eeprom_mapping = {
+ 1: "/sys/bus/i2c/devices/i2c-42/42-0050/eeprom", 21: "/sys/bus/i2c/devices/i2c-46/46-0050/eeprom",
+ 2: "/sys/bus/i2c/devices/i2c-43/43-0050/eeprom", 22: "/sys/bus/i2c/devices/i2c-47/47-0050/eeprom",
+ 3: "/sys/bus/i2c/devices/i2c-10/10-0050/eeprom", 23: "/sys/bus/i2c/devices/i2c-26/26-0050/eeprom",
+ 4: "/sys/bus/i2c/devices/i2c-11/11-0050/eeprom", 24: "/sys/bus/i2c/devices/i2c-27/27-0050/eeprom",
+ 5: "/sys/bus/i2c/devices/i2c-12/12-0050/eeprom", 25: "/sys/bus/i2c/devices/i2c-28/28-0050/eeprom",
+ 6: "/sys/bus/i2c/devices/i2c-13/13-0050/eeprom", 26: "/sys/bus/i2c/devices/i2c-29/29-0050/eeprom",
+ 7: "/sys/bus/i2c/devices/i2c-14/14-0050/eeprom", 27: "/sys/bus/i2c/devices/i2c-30/30-0050/eeprom",
+ 8: "/sys/bus/i2c/devices/i2c-15/15-0050/eeprom", 28: "/sys/bus/i2c/devices/i2c-31/31-0050/eeprom",
+ 9: "/sys/bus/i2c/devices/i2c-16/16-0050/eeprom", 29: "/sys/bus/i2c/devices/i2c-32/32-0050/eeprom",
+ 10: "/sys/bus/i2c/devices/i2c-17/17-0050/eeprom", 30: "/sys/bus/i2c/devices/i2c-33/33-0050/eeprom",
+ 11: "/sys/bus/i2c/devices/i2c-18/18-0050/eeprom", 31: "/sys/bus/i2c/devices/i2c-34/34-0050/eeprom",
+ 12: "/sys/bus/i2c/devices/i2c-19/19-0050/eeprom", 32: "/sys/bus/i2c/devices/i2c-35/35-0050/eeprom",
+ 13: "/sys/bus/i2c/devices/i2c-20/20-0050/eeprom", 33: "/sys/bus/i2c/devices/i2c-36/36-0050/eeprom",
+ 14: "/sys/bus/i2c/devices/i2c-21/21-0050/eeprom", 34: "/sys/bus/i2c/devices/i2c-37/37-0050/eeprom",
+ 15: "/sys/bus/i2c/devices/i2c-22/22-0050/eeprom", 35: "/sys/bus/i2c/devices/i2c-38/38-0050/eeprom",
+ 16: "/sys/bus/i2c/devices/i2c-23/23-0050/eeprom", 36: "/sys/bus/i2c/devices/i2c-39/39-0050/eeprom",
+ 17: "/sys/bus/i2c/devices/i2c-24/24-0050/eeprom", 37: "/sys/bus/i2c/devices/i2c-40/40-0050/eeprom",
+ 18: "/sys/bus/i2c/devices/i2c-25/25-0050/eeprom", 38: "/sys/bus/i2c/devices/i2c-41/41-0050/eeprom",
+ 19: "/sys/bus/i2c/devices/i2c-44/44-0050/eeprom", 39: "/sys/bus/i2c/devices/i2c-48/48-0050/eeprom",
+ 20: "/sys/bus/i2c/devices/i2c-45/45-0050/eeprom", 40: "/sys/bus/i2c/devices/i2c-49/49-0050/eeprom",
+ }
+ _port_to_i2cbus_mapping = {
+ 1: 42, 2: 43, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14, 8: 15, 9: 16, 10: 17,
+ 11: 18, 12: 19, 13: 20, 14: 21, 15: 22, 16: 23, 17: 24, 18: 25, 19: 44, 20: 45,
+ 21: 46, 22: 47, 23: 26, 24: 27, 25: 28, 26: 29, 27: 30, 28: 31, 29: 32, 30: 33,
+ 31: 34, 32: 35, 33: 36, 34: 37, 35: 38, 36: 39, 37: 40, 38: 41, 39: 48, 40: 49,
+ }
+
+ @property
+ def port_start(self):
+ return self.PORT_START
+
+ @property
+ def port_end(self):
+ return self.PORT_END
+
+ @property
+ def qsfp_ports(self):
+ return range(self.QSFP_PORT_START, self.QSFP_PORT_END + 1)
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+ @property
+ def port_to_i2cbus_mapping(self):
+ return self._port_to_i2cbus_mapping
+
+ def get_port_name(self, port_num):
+ if port_num in self.qsfp_ports:
+ self._port_name = "QSFP" + str(port_num - self.QSFP_PORT_START + 1)
+ else:
+ self._port_name = "SFP" + str(port_num)
+ return self._port_name
+
+ def get_eeprom_dom_raw(self, port_num):
+ if port_num in self.qsfp_ports:
+ # QSFP DOM EEPROM is also at addr 0x50 and thus also stored in eeprom_ifraw
+ return None
+ else:
+ # Read dom eeprom at addr 0x51
+ return self._read_eeprom_devid(port_num, self.DOM_EEPROM_ADDR, 256)
+
+ def __init__(self):
+ # Override port_to_eeprom_mapping for class initialization
+ eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'
+ # the following scheme is not correct,use 'i2cdetect -y -l' to detect #
+ #for x in range(self.PORT_START, self.PORT_END+1):
+ # self.port_to_i2cbus_mapping[x] = (x + self.EEPROM_OFFSET)
+ # self.port_to_eeprom_mapping[x] = eeprom_path.format(
+ # x + self.EEPROM_OFFSET)
+ print("self.port_to_i2cbus_mapping: "+str(self.port_to_i2cbus_mapping)+"\n")
+ print("self.port_to_eeprom_mapping: "+str(self.port_to_eeprom_mapping)+"\n")
+
+ SfpUtilBase.__init__(self)
+
+ def get_presence(self, port_num):
+
+ # Check for invalid port_num
+ if port_num not in range(self.port_start, self.port_end + 1):
+ return False
+
+ # Get path for access port presence status
+ port_name = self.get_port_name(port_num)
+ sysfs_filename = "qsfp_modprs" if port_num in self.qsfp_ports else "sfp_modabs"
+ reg_path = "/".join([self.PORT_INFO_PATH, port_name, sysfs_filename])
+
+ # Read status
+ try:
+ reg_file = open(reg_path)
+ content = reg_file.readline().rstrip()
+ reg_value = int(content)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ # Module present is active low
+ if reg_value == 0:
+ return True
+
+ return False
+
+ def get_low_power_mode(self, port_num):
+ return NotImplementedError
+
+ def set_low_power_mode(self, port_num, lpmode):
+ # Check for invalid QSFP port_num
+ if port_num not in self.qsfp_ports:
+ return False
+
+ try:
+ port_name = self.get_port_name(port_num)
+ reg_file = open(
+ "/".join([self.PORT_INFO_PATH, port_name, "qsfp_lpmode"]), "r+")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = hex(lpmode)
+
+ reg_file.seek(0)
+ reg_file.write(content)
+ reg_file.close()
+
+ return True
+
+ def reset(self, port_num):
+ # Check for invalid QSFP port_num
+ if port_num not in self.qsfp_ports:
+ return False
+
+ try:
+ port_name = self.get_port_name(port_num)
+ reg_file = open(
+ "/".join([self.PORT_INFO_PATH, port_name, "qsfp_reset"]), "w")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ # Convert our register value back to a hex string and write back
+ reg_file.seek(0)
+ reg_file.write(hex(0))
+ reg_file.close()
+
+ # Sleep 1 second to allow it to settle
+ time.sleep(1)
+
+ # Flip the bit back high and write back to the register to take port out of reset
+ try:
+ reg_file = open(
+ "/".join([self.PORT_INFO_PATH, port_name, "qsfp_reset"]), "w")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_file.seek(0)
+ reg_file.write(hex(1))
+ reg_file.close()
+
+ return True
+
+ def get_transceiver_change_event(self, timeout=0):
+ """
+ TBD
+ """
+ return NotImplementedError
+
+ def tx_disable(self, port_num, disable):
+ """
+ @param port_num index of physical port
+ @param disable, True -- disable port tx signal
+ False -- enable port tx signal
+ @return True when operation success, False on failure.
+ """
+ TX_DISABLE_BYTE_OFFSET = 86
+ if port_num not in range(self.port_start, self.port_end + 1) or type(disable) != bool:
+ return False
+
+ # QSFP, set eeprom to disable tx
+ if port_num in self.qsfp_ports:
+ presence = self.get_presence(port_num)
+ if not presence:
+ return True
+
+ disable = b'\x0f' if disable else b'\x00'
+ # open eeprom
+ try:
+ with open(self.port_to_eeprom_mapping[port_num], mode="wb", buffering=0) as sysfsfile:
+ sysfsfile.seek(TX_DISABLE_BYTE_OFFSET)
+ sysfsfile.write(bytearray(disable))
+ except IOError:
+ return False
+ except:
+ return False
+
+ # SFP, set tx_disable pin
+ else:
+ try:
+ disable = hex(1) if disable else hex(0)
+ port_name = self.get_port_name(port_num)
+ reg_file = open(
+ "/".join([self.PORT_INFO_PATH, port_name, "sfp_txdisable"]), "w")
+ reg_file.write(disable)
+ reg_file.close()
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ return True
diff --git a/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/td3-as14-40d.config.bcm b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/td3-as14-40d.config.bcm
new file mode 100644
index 000000000000..2aaef4ea27ea
--- /dev/null
+++ b/device/alibaba/x86_64-alibaba_as14-40d-cl-r0/td3-as14-40d.config.bcm
@@ -0,0 +1,590 @@
+ifp_inports_support_enable=1
+ipv6_lpm_128b_enable=0x1
+l2_mem_entries=32768
+l2xmsg_mode=1
+l3_max_ecmp_mode=1
+l3_mem_entries=16384
+lpm_scaling_enable=1
+max_vp_lags=0
+mem_cache_enable=0
+miim_intr_enable=0
+module_64ports=1
+oversubscribe_mode=1
+parity_enable=0
+serdes_if_type_ce=14
+#pbmp_xport_xe=0x48878787f8787808dfe1e0203e1e1e022
+pbmp_xport_xe=0x88888888888888882222222222222222
+
+#ptp_ts_pll_fref=50000000
+#ptp_bs_fref_0=50000000
+#ptp_bs_fref_1=50000000
+portmap_1.0=1:100
+portmap_5.0=5:100
+portmap_9.0=9:100
+portmap_13.0=13:100
+portmap_17.0=17:100
+portmap_21.0=21:100
+portmap_25.0=25:100
+portmap_29.0=29:100
+portmap_33.0=33:100
+portmap_37.0=37:100
+portmap_41.0=41:100
+portmap_45.0=45:100
+portmap_49.0=49:100
+portmap_53.0=53:100
+portmap_57.0=57:100
+portmap_61.0=61:100
+portmap_67.0=65:100
+portmap_71.0=69:100
+portmap_75.0=73:100
+portmap_79.0=77:100
+portmap_83.0=81:100
+portmap_87.0=85:100
+portmap_91.0=89:100
+portmap_95.0=93:100
+portmap_99.0=97:100
+portmap_103.0=101:100
+portmap_107.0=105:100
+portmap_111.0=109:100
+portmap_115.0=113:100
+portmap_119.0=117:100
+portmap_123.0=121:100
+portmap_127.0=125:100
+portmap_66.0=129:10:m
+portmap_130.0=128:10:m
+
+#wc0 lane swap
+phy_chain_tx_lane_map_physical{1.0}=0x0132
+phy_chain_rx_lane_map_physical{1.0}=0x3210
+
+#wc1 lane swap
+phy_chain_tx_lane_map_physical{5.0}=0x2301
+phy_chain_rx_lane_map_physical{5.0}=0x2031
+
+#wc2 lane swap
+phy_chain_tx_lane_map_physical{9.0}=0x0132
+phy_chain_rx_lane_map_physical{9.0}=0x3210
+
+#wc3 lane swap
+phy_chain_tx_lane_map_physical{13.0}=0x3201
+phy_chain_rx_lane_map_physical{13.0}=0x2031
+
+#wc4 lane swap
+phy_chain_tx_lane_map_physical{17.0}=0x0123
+phy_chain_rx_lane_map_physical{17.0}=0x3210
+
+#wc5 lane swap
+phy_chain_tx_lane_map_physical{21.0}=0x2301
+phy_chain_rx_lane_map_physical{21.0}=0x2031
+
+#wc6 lane swap
+phy_chain_tx_lane_map_physical{25.0}=0x0123
+phy_chain_rx_lane_map_physical{25.0}=0x3210
+
+#wc7 lane swap
+phy_chain_tx_lane_map_physical{29.0}=0x3201
+phy_chain_rx_lane_map_physical{29.0}=0x2031
+
+#wc8 lane swap
+phy_chain_tx_lane_map_physical{33.0}=0x0213
+phy_chain_rx_lane_map_physical{33.0}=0x1302
+
+#wc9 lane swap
+phy_chain_tx_lane_map_physical{37.0}=0x1302
+phy_chain_rx_lane_map_physical{37.0}=0x2031
+
+#wc10 lane swap
+phy_chain_tx_lane_map_physical{41.0}=0x0231
+phy_chain_rx_lane_map_physical{41.0}=0x3120
+
+#wc11 lane swap
+phy_chain_tx_lane_map_physical{45.0}=0x1302
+phy_chain_rx_lane_map_physical{45.0}=0x2031
+
+#wc12 lane swap
+phy_chain_tx_lane_map_physical{49.0}=0x2103
+phy_chain_rx_lane_map_physical{49.0}=0x3120
+
+#wc13 lane swap
+phy_chain_tx_lane_map_physical{53.0}=0x2301
+phy_chain_rx_lane_map_physical{53.0}=0x2031
+
+#wc14 lane swap
+phy_chain_tx_lane_map_physical{57.0}=0x0123
+phy_chain_rx_lane_map_physical{57.0}=0x2301
+
+#wc15 lane swap
+phy_chain_tx_lane_map_physical{61.0}=0x3210
+phy_chain_rx_lane_map_physical{61.0}=0x1032
+
+#wc16 lane swap
+phy_chain_tx_lane_map_physical{65.0}=0x3210
+phy_chain_rx_lane_map_physical{65.0}=0x1023
+
+#wc17 lane swap
+phy_chain_tx_lane_map_physical{69.0}=0x0123
+phy_chain_rx_lane_map_physical{69.0}=0x1302
+
+#wc18 lane swap
+phy_chain_tx_lane_map_physical{73.0}=0x2301
+phy_chain_rx_lane_map_physical{73.0}=0x1032
+
+#wc19 lane swap
+phy_chain_tx_lane_map_physical{77.0}=0x2013
+phy_chain_rx_lane_map_physical{77.0}=0x3120
+
+#wc20 lane swap
+phy_chain_tx_lane_map_physical{81.0}=0x1302
+phy_chain_rx_lane_map_physical{81.0}=0x2031
+
+#wc21 lane swap
+phy_chain_tx_lane_map_physical{85.0}=0x0123
+phy_chain_rx_lane_map_physical{85.0}=0x2130
+
+#wc22 lane swap
+phy_chain_tx_lane_map_physical{89.0}=0x2301
+phy_chain_rx_lane_map_physical{89.0}=0x2031
+
+#wc23 lane swap
+phy_chain_tx_lane_map_physical{93.0}=0x0312
+phy_chain_rx_lane_map_physical{93.0}=0x2310
+
+#wc24 lane swap
+phy_chain_tx_lane_map_physical{97.0}=0x2301
+phy_chain_rx_lane_map_physical{97.0}=0x1032
+
+#wc25 lane swap
+phy_chain_tx_lane_map_physical{101.0}=0x0123
+phy_chain_rx_lane_map_physical{101.0}=0x3210
+
+#wc26 lane swap
+phy_chain_tx_lane_map_physical{105.0}=0x2301
+phy_chain_rx_lane_map_physical{105.0}=0x1032
+
+#wc27 lane swap
+phy_chain_tx_lane_map_physical{109.0}=0x0123
+phy_chain_rx_lane_map_physical{109.0}=0x3210
+
+#wc28 lane swap
+phy_chain_tx_lane_map_physical{113.0}=0x2301
+phy_chain_rx_lane_map_physical{113.0}=0x2031
+
+#wc29 lane swap
+phy_chain_tx_lane_map_physical{117.0}=0x0123
+phy_chain_rx_lane_map_physical{117.0}=0x3210
+
+#wc30 lane swap
+phy_chain_tx_lane_map_physical{121.0}=0x2301
+phy_chain_rx_lane_map_physical{121.0}=0x1032
+
+#wc31 lane swap
+phy_chain_tx_lane_map_physical{125.0}=0x0123
+phy_chain_rx_lane_map_physical{125.0}=0x3210
+
+#MC lane swap
+phy_chain_tx_lane_map_physical{129.0}=0x3210
+phy_chain_rx_lane_map_physical{129.0}=0x3210
+
+
+#wc0 P/N flip
+phy_chain_tx_polarity_flip_physical{1.0}=0x0
+phy_chain_rx_polarity_flip_physical{1.0}=0x0
+phy_chain_tx_polarity_flip_physical{2.0}=0x0
+phy_chain_rx_polarity_flip_physical{2.0}=0x1
+phy_chain_tx_polarity_flip_physical{3.0}=0x0
+phy_chain_rx_polarity_flip_physical{3.0}=0x0
+phy_chain_tx_polarity_flip_physical{4.0}=0x1
+phy_chain_rx_polarity_flip_physical{4.0}=0x1
+
+#wc1 P/N flip
+phy_chain_tx_polarity_flip_physical{5.0}=0x0
+phy_chain_rx_polarity_flip_physical{5.0}=0x0
+phy_chain_tx_polarity_flip_physical{6.0}=0x1
+phy_chain_rx_polarity_flip_physical{6.0}=0x1
+phy_chain_tx_polarity_flip_physical{7.0}=0x0
+phy_chain_rx_polarity_flip_physical{7.0}=0x1
+phy_chain_tx_polarity_flip_physical{8.0}=0x1
+phy_chain_rx_polarity_flip_physical{8.0}=0x1
+
+#wc2 P/N flip
+phy_chain_tx_polarity_flip_physical{9.0}=0x0
+phy_chain_rx_polarity_flip_physical{9.0}=0x0
+phy_chain_tx_polarity_flip_physical{10.0}=0x0
+phy_chain_rx_polarity_flip_physical{10.0}=0x1
+phy_chain_tx_polarity_flip_physical{11.0}=0x0
+phy_chain_rx_polarity_flip_physical{11.0}=0x0
+phy_chain_tx_polarity_flip_physical{12.0}=0x1
+phy_chain_rx_polarity_flip_physical{12.0}=0x1
+
+#wc3 P/N flip
+phy_chain_tx_polarity_flip_physical{13.0}=0x0
+phy_chain_rx_polarity_flip_physical{13.0}=0x0
+phy_chain_tx_polarity_flip_physical{14.0}=0x1
+phy_chain_rx_polarity_flip_physical{14.0}=0x1
+phy_chain_tx_polarity_flip_physical{15.0}=0x0
+phy_chain_rx_polarity_flip_physical{15.0}=0x1
+phy_chain_tx_polarity_flip_physical{16.0}=0x0
+phy_chain_rx_polarity_flip_physical{16.0}=0x1
+
+#wc4 P/N flip
+phy_chain_tx_polarity_flip_physical{17.0}=0x0
+phy_chain_rx_polarity_flip_physical{17.0}=0x0
+phy_chain_tx_polarity_flip_physical{18.0}=0x1
+phy_chain_rx_polarity_flip_physical{18.0}=0x1
+phy_chain_tx_polarity_flip_physical{19.0}=0x0
+phy_chain_rx_polarity_flip_physical{19.0}=0x0
+phy_chain_tx_polarity_flip_physical{20.0}=0x1
+phy_chain_rx_polarity_flip_physical{20.0}=0x1
+
+#wc5 P/N flip
+phy_chain_tx_polarity_flip_physical{21.0}=0x0
+phy_chain_rx_polarity_flip_physical{21.0}=0x0
+phy_chain_tx_polarity_flip_physical{22.0}=0x1
+phy_chain_rx_polarity_flip_physical{22.0}=0x1
+phy_chain_tx_polarity_flip_physical{23.0}=0x0
+phy_chain_rx_polarity_flip_physical{23.0}=0x1
+phy_chain_tx_polarity_flip_physical{24.0}=0x1
+phy_chain_rx_polarity_flip_physical{24.0}=0x1
+
+#wc6 P/N flip
+phy_chain_tx_polarity_flip_physical{25.0}=0x0
+phy_chain_rx_polarity_flip_physical{25.0}=0x1
+phy_chain_tx_polarity_flip_physical{26.0}=0x1
+phy_chain_rx_polarity_flip_physical{26.0}=0x0
+phy_chain_tx_polarity_flip_physical{27.0}=0x0
+phy_chain_rx_polarity_flip_physical{27.0}=0x1
+phy_chain_tx_polarity_flip_physical{28.0}=0x1
+phy_chain_rx_polarity_flip_physical{28.0}=0x0
+
+#wc7 P/N flip
+phy_chain_tx_polarity_flip_physical{29.0}=0x1
+phy_chain_rx_polarity_flip_physical{29.0}=0x1
+phy_chain_tx_polarity_flip_physical{30.0}=0x1
+phy_chain_rx_polarity_flip_physical{30.0}=0x0
+phy_chain_tx_polarity_flip_physical{31.0}=0x0
+phy_chain_rx_polarity_flip_physical{31.0}=0x0
+phy_chain_tx_polarity_flip_physical{32.0}=0x0
+phy_chain_rx_polarity_flip_physical{32.0}=0x0
+
+#wc8 P/N flip
+phy_chain_tx_polarity_flip_physical{33.0}=0x1
+phy_chain_rx_polarity_flip_physical{33.0}=0x1
+phy_chain_tx_polarity_flip_physical{34.0}=0x0
+phy_chain_rx_polarity_flip_physical{34.0}=0x0
+phy_chain_tx_polarity_flip_physical{35.0}=0x0
+phy_chain_rx_polarity_flip_physical{35.0}=0x0
+phy_chain_tx_polarity_flip_physical{36.0}=0x1
+phy_chain_rx_polarity_flip_physical{36.0}=0x0
+
+#wc9 P/N flip
+phy_chain_tx_polarity_flip_physical{37.0}=0x1
+phy_chain_rx_polarity_flip_physical{37.0}=0x1
+phy_chain_tx_polarity_flip_physical{38.0}=0x1
+phy_chain_rx_polarity_flip_physical{38.0}=0x0
+phy_chain_tx_polarity_flip_physical{39.0}=0x1
+phy_chain_rx_polarity_flip_physical{39.0}=0x0
+phy_chain_tx_polarity_flip_physical{40.0}=0x0
+phy_chain_rx_polarity_flip_physical{40.0}=0x1
+
+#wc10 P/N flip
+phy_chain_tx_polarity_flip_physical{41.0}=0x1
+phy_chain_rx_polarity_flip_physical{41.0}=0x1
+phy_chain_tx_polarity_flip_physical{42.0}=0x0
+phy_chain_rx_polarity_flip_physical{42.0}=0x1
+phy_chain_tx_polarity_flip_physical{43.0}=0x1
+phy_chain_rx_polarity_flip_physical{43.0}=0x0
+phy_chain_tx_polarity_flip_physical{44.0}=0x1
+phy_chain_rx_polarity_flip_physical{44.0}=0x1
+
+#wc11 P/N flip
+phy_chain_tx_polarity_flip_physical{45.0}=0x1
+phy_chain_rx_polarity_flip_physical{45.0}=0x0
+phy_chain_tx_polarity_flip_physical{46.0}=0x1
+phy_chain_rx_polarity_flip_physical{46.0}=0x0
+phy_chain_tx_polarity_flip_physical{47.0}=0x1
+phy_chain_rx_polarity_flip_physical{47.0}=0x1
+phy_chain_tx_polarity_flip_physical{48.0}=0x0
+phy_chain_rx_polarity_flip_physical{48.0}=0x1
+
+#wc12 P/N flip
+phy_chain_tx_polarity_flip_physical{49.0}=0x1
+phy_chain_rx_polarity_flip_physical{49.0}=0x0
+phy_chain_tx_polarity_flip_physical{50.0}=0x1
+phy_chain_rx_polarity_flip_physical{50.0}=0x0
+phy_chain_tx_polarity_flip_physical{51.0}=0x0
+phy_chain_rx_polarity_flip_physical{51.0}=0x1
+phy_chain_tx_polarity_flip_physical{52.0}=0x1
+phy_chain_rx_polarity_flip_physical{52.0}=0x1
+
+#wc13 P/N flip
+phy_chain_tx_polarity_flip_physical{53.0}=0x0
+phy_chain_rx_polarity_flip_physical{53.0}=0x0
+phy_chain_tx_polarity_flip_physical{54.0}=0x1
+phy_chain_rx_polarity_flip_physical{54.0}=0x1
+phy_chain_tx_polarity_flip_physical{55.0}=0x0
+phy_chain_rx_polarity_flip_physical{55.0}=0x1
+phy_chain_tx_polarity_flip_physical{56.0}=0x1
+phy_chain_rx_polarity_flip_physical{56.0}=0x1
+
+#wc14 P/N flip
+phy_chain_tx_polarity_flip_physical{57.0}=0x1
+phy_chain_rx_polarity_flip_physical{57.0}=0x0
+phy_chain_tx_polarity_flip_physical{58.0}=0x1
+phy_chain_rx_polarity_flip_physical{58.0}=0x1
+phy_chain_tx_polarity_flip_physical{59.0}=0x0
+phy_chain_rx_polarity_flip_physical{59.0}=0x0
+phy_chain_tx_polarity_flip_physical{60.0}=0x1
+phy_chain_rx_polarity_flip_physical{60.0}=0x1
+
+#wc15 P/N flip
+phy_chain_tx_polarity_flip_physical{61.0}=0x0
+phy_chain_rx_polarity_flip_physical{61.0}=0x1
+phy_chain_tx_polarity_flip_physical{62.0}=0x1
+phy_chain_rx_polarity_flip_physical{62.0}=0x0
+phy_chain_tx_polarity_flip_physical{63.0}=0x0
+phy_chain_rx_polarity_flip_physical{63.0}=0x1
+phy_chain_tx_polarity_flip_physical{64.0}=0x0
+phy_chain_rx_polarity_flip_physical{64.0}=0x0
+
+#wc16 P/N flip
+phy_chain_tx_polarity_flip_physical{65.0}=0x1
+phy_chain_rx_polarity_flip_physical{65.0}=0x0
+phy_chain_tx_polarity_flip_physical{66.0}=0x0
+phy_chain_rx_polarity_flip_physical{66.0}=0x0
+phy_chain_tx_polarity_flip_physical{67.0}=0x1
+phy_chain_rx_polarity_flip_physical{67.0}=0x1
+phy_chain_tx_polarity_flip_physical{68.0}=0x0
+phy_chain_rx_polarity_flip_physical{68.0}=0x0
+
+#wc17 P/N flip
+phy_chain_tx_polarity_flip_physical{69.0}=0x1
+phy_chain_rx_polarity_flip_physical{69.0}=0x1
+phy_chain_tx_polarity_flip_physical{70.0}=0x0
+phy_chain_rx_polarity_flip_physical{70.0}=0x0
+phy_chain_tx_polarity_flip_physical{71.0}=0x1
+phy_chain_rx_polarity_flip_physical{71.0}=0x0
+phy_chain_tx_polarity_flip_physical{72.0}=0x0
+phy_chain_rx_polarity_flip_physical{72.0}=0x0
+
+#wc18 P/N flip
+phy_chain_tx_polarity_flip_physical{73.0}=0x0
+phy_chain_rx_polarity_flip_physical{73.0}=0x1
+phy_chain_tx_polarity_flip_physical{74.0}=0x1
+phy_chain_rx_polarity_flip_physical{74.0}=0x0
+phy_chain_tx_polarity_flip_physical{75.0}=0x0
+phy_chain_rx_polarity_flip_physical{75.0}=0x1
+phy_chain_tx_polarity_flip_physical{76.0}=0x1
+phy_chain_rx_polarity_flip_physical{76.0}=0x0
+
+#wc19 P/N flip
+phy_chain_tx_polarity_flip_physical{77.0}=0x0
+phy_chain_rx_polarity_flip_physical{77.0}=0x0
+phy_chain_tx_polarity_flip_physical{78.0}=0x0
+phy_chain_rx_polarity_flip_physical{78.0}=0x0
+phy_chain_tx_polarity_flip_physical{79.0}=0x1
+phy_chain_rx_polarity_flip_physical{79.0}=0x1
+phy_chain_tx_polarity_flip_physical{80.0}=0x1
+phy_chain_rx_polarity_flip_physical{80.0}=0x1
+
+#wc20 P/N flip
+phy_chain_tx_polarity_flip_physical{81.0}=0x0
+phy_chain_rx_polarity_flip_physical{81.0}=0x0
+phy_chain_tx_polarity_flip_physical{82.0}=0x0
+phy_chain_rx_polarity_flip_physical{82.0}=0x0
+phy_chain_tx_polarity_flip_physical{83.0}=0x1
+phy_chain_rx_polarity_flip_physical{83.0}=0x1
+phy_chain_tx_polarity_flip_physical{84.0}=0x1
+phy_chain_rx_polarity_flip_physical{84.0}=0x0
+
+#wc21 P/N flip
+phy_chain_tx_polarity_flip_physical{85.0}=0x1
+phy_chain_rx_polarity_flip_physical{85.0}=0x1
+phy_chain_tx_polarity_flip_physical{86.0}=0x0
+phy_chain_rx_polarity_flip_physical{86.0}=0x1
+phy_chain_tx_polarity_flip_physical{87.0}=0x1
+phy_chain_rx_polarity_flip_physical{87.0}=0x0
+phy_chain_tx_polarity_flip_physical{88.0}=0x0
+phy_chain_rx_polarity_flip_physical{88.0}=0x0
+
+#wc22 P/N flip
+phy_chain_tx_polarity_flip_physical{89.0}=0x1
+phy_chain_rx_polarity_flip_physical{89.0}=0x0
+phy_chain_tx_polarity_flip_physical{90.0}=0x0
+phy_chain_rx_polarity_flip_physical{90.0}=0x0
+phy_chain_tx_polarity_flip_physical{91.0}=0x1
+phy_chain_rx_polarity_flip_physical{91.0}=0x1
+phy_chain_tx_polarity_flip_physical{92.0}=0x0
+phy_chain_rx_polarity_flip_physical{92.0}=0x1
+
+#wc23 P/N flip
+phy_chain_tx_polarity_flip_physical{93.0}=0x1
+phy_chain_rx_polarity_flip_physical{93.0}=0x1
+phy_chain_tx_polarity_flip_physical{94.0}=0x1
+phy_chain_rx_polarity_flip_physical{94.0}=0x1
+phy_chain_tx_polarity_flip_physical{95.0}=0x0
+phy_chain_rx_polarity_flip_physical{95.0}=0x0
+phy_chain_tx_polarity_flip_physical{96.0}=0x0
+phy_chain_rx_polarity_flip_physical{96.0}=0x1
+
+#wc24 P/N flip
+phy_chain_tx_polarity_flip_physical{97.0}=0x1
+phy_chain_rx_polarity_flip_physical{97.0}=0x1
+phy_chain_tx_polarity_flip_physical{98.0}=0x0
+phy_chain_rx_polarity_flip_physical{98.0}=0x0
+phy_chain_tx_polarity_flip_physical{99.0}=0x1
+phy_chain_rx_polarity_flip_physical{99.0}=0x1
+phy_chain_tx_polarity_flip_physical{100.0}=0x0
+phy_chain_rx_polarity_flip_physical{100.0}=0x0
+
+#wc25 P/N flip
+phy_chain_tx_polarity_flip_physical{101.0}=0x1
+phy_chain_rx_polarity_flip_physical{101.0}=0x0
+phy_chain_tx_polarity_flip_physical{102.0}=0x0
+phy_chain_rx_polarity_flip_physical{102.0}=0x1
+phy_chain_tx_polarity_flip_physical{103.0}=0x1
+phy_chain_rx_polarity_flip_physical{103.0}=0x0
+phy_chain_tx_polarity_flip_physical{104.0}=0x0
+phy_chain_rx_polarity_flip_physical{104.0}=0x0
+
+#wc26 P/N flip
+phy_chain_tx_polarity_flip_physical{105.0}=0x1
+phy_chain_rx_polarity_flip_physical{105.0}=0x0
+phy_chain_tx_polarity_flip_physical{106.0}=0x0
+phy_chain_rx_polarity_flip_physical{106.0}=0x1
+phy_chain_tx_polarity_flip_physical{107.0}=0x1
+phy_chain_rx_polarity_flip_physical{107.0}=0x0
+phy_chain_tx_polarity_flip_physical{108.0}=0x0
+phy_chain_rx_polarity_flip_physical{108.0}=0x1
+
+#wc27 P/N flip
+phy_chain_tx_polarity_flip_physical{109.0}=0x1
+phy_chain_rx_polarity_flip_physical{109.0}=0x1
+phy_chain_tx_polarity_flip_physical{110.0}=0x0
+phy_chain_rx_polarity_flip_physical{110.0}=0x0
+phy_chain_tx_polarity_flip_physical{111.0}=0x1
+phy_chain_rx_polarity_flip_physical{111.0}=0x1
+phy_chain_tx_polarity_flip_physical{112.0}=0x0
+phy_chain_rx_polarity_flip_physical{112.0}=0x0
+
+#wc28 P/N flip
+phy_chain_tx_polarity_flip_physical{113.0}=0x1
+phy_chain_rx_polarity_flip_physical{113.0}=0x1
+phy_chain_tx_polarity_flip_physical{114.0}=0x0
+phy_chain_rx_polarity_flip_physical{114.0}=0x0
+phy_chain_tx_polarity_flip_physical{115.0}=0x1
+phy_chain_rx_polarity_flip_physical{115.0}=0x0
+phy_chain_tx_polarity_flip_physical{116.0}=0x0
+phy_chain_rx_polarity_flip_physical{116.0}=0x0
+
+#wc29 P/N flip
+phy_chain_tx_polarity_flip_physical{117.0}=0x1
+phy_chain_rx_polarity_flip_physical{117.0}=0x1
+phy_chain_tx_polarity_flip_physical{118.0}=0x0
+phy_chain_rx_polarity_flip_physical{118.0}=0x0
+phy_chain_tx_polarity_flip_physical{119.0}=0x1
+phy_chain_rx_polarity_flip_physical{119.0}=0x1
+phy_chain_tx_polarity_flip_physical{120.0}=0x0
+phy_chain_rx_polarity_flip_physical{120.0}=0x0
+
+#wc30 P/N flip
+phy_chain_tx_polarity_flip_physical{121.0}=0x1
+phy_chain_rx_polarity_flip_physical{121.0}=0x0
+phy_chain_tx_polarity_flip_physical{122.0}=0x0
+phy_chain_rx_polarity_flip_physical{122.0}=0x1
+phy_chain_tx_polarity_flip_physical{123.0}=0x1
+phy_chain_rx_polarity_flip_physical{123.0}=0x0
+phy_chain_tx_polarity_flip_physical{124.0}=0x0
+phy_chain_rx_polarity_flip_physical{124.0}=0x1
+
+#wc31 P/N flip
+phy_chain_tx_polarity_flip_physical{125.0}=0x1
+phy_chain_rx_polarity_flip_physical{125.0}=0x1
+phy_chain_tx_polarity_flip_physical{126.0}=0x0
+phy_chain_rx_polarity_flip_physical{126.0}=0x0
+phy_chain_tx_polarity_flip_physical{127.0}=0x1
+phy_chain_rx_polarity_flip_physical{127.0}=0x1
+phy_chain_tx_polarity_flip_physical{128.0}=0x0
+phy_chain_rx_polarity_flip_physical{128.0}=0x0
+
+#MC P/N flip
+phy_chain_tx_polarity_flip_physical{129.0}=0x0
+phy_chain_rx_polarity_flip_physical{129.0}=0x0
+phy_chain_tx_polarity_flip_physical{130.0}=0x0
+phy_chain_rx_polarity_flip_physical{130.0}=0x0
+phy_chain_tx_polarity_flip_physical{131.0}=0x0
+phy_chain_rx_polarity_flip_physical{131.0}=0x0
+phy_chain_tx_polarity_flip_physical{132.0}=0x0
+phy_chain_rx_polarity_flip_physical{132.0}=0x0
+
+dport_map_port_1=1
+dport_map_port_5=2
+dport_map_port_9=3
+dport_map_port_13=4
+dport_map_port_17=5
+dport_map_port_21=6
+dport_map_port_25=7
+dport_map_port_29=8
+dport_map_port_33=9
+dport_map_port_37=10
+dport_map_port_41=11
+dport_map_port_45=12
+dport_map_port_49=13
+dport_map_port_53=14
+dport_map_port_57=15
+dport_map_port_61=16
+dport_map_port_67=17
+dport_map_port_71=18
+dport_map_port_75=19
+dport_map_port_79=20
+dport_map_port_83=21
+dport_map_port_87=22
+dport_map_port_91=23
+dport_map_port_95=24
+dport_map_port_99=25
+dport_map_port_103=26
+dport_map_port_107=27
+dport_map_port_111=28
+dport_map_port_115=29
+dport_map_port_119=30
+dport_map_port_123=31
+dport_map_port_127=32
+dport_map_port_66=33
+dport_map_port_130=34
+
+# configuration for 100G optical module
+serdes_preemphasis_1=0x164608
+serdes_preemphasis_5=0x164608
+serdes_preemphasis_9=0x164608
+serdes_preemphasis_13=0x134908
+serdes_preemphasis_17=0x134908
+serdes_preemphasis_21=0x134908
+serdes_preemphasis_25=0x124a08
+serdes_preemphasis_29=0x124a08
+serdes_preemphasis_33=0x114b08
+serdes_preemphasis_37=0x114b08
+serdes_preemphasis_41=0x0f4d08
+serdes_preemphasis_45=0x0f4d08
+serdes_preemphasis_49=0x0d4f08
+serdes_preemphasis_53=0x0d4f08
+serdes_preemphasis_57=0x0d4f08
+serdes_preemphasis_61=0x0d4f08
+serdes_preemphasis_67=0x0d4f08
+serdes_preemphasis_71=0x0d4f08
+serdes_preemphasis_75=0x0d4f08
+serdes_preemphasis_79=0x0d4f08
+serdes_preemphasis_83=0x0d4f08
+serdes_preemphasis_87=0x0f4d08
+serdes_preemphasis_91=0x0f4d08
+serdes_preemphasis_95=0x0f4d08
+serdes_preemphasis_99=0x114b08
+serdes_preemphasis_103=0x114b08
+serdes_preemphasis_107=0x114b08
+serdes_preemphasis_111=0x124a08
+serdes_preemphasis_115=0x134908
+serdes_preemphasis_119=0x134908
+serdes_preemphasis_123=0x134908
+serdes_preemphasis_127=0x164608
+
+schan_intr_enable=0
+stable_size=0x5500000
+tdma_timeout_usec=3000000
diff --git a/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/port_config.ini b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/port_config.ini
new file mode 100644
index 000000000000..d3d339076a59
--- /dev/null
+++ b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/port_config.ini
@@ -0,0 +1,35 @@
+# name lanes alias index
+Ethernet0 1,2,3,4 Ethernet1/1 1
+Ethernet4 5,6,7,8 Ethernet2/1 2
+Ethernet8 9,10,11,12 Ethernet3/1 3
+Ethernet12 13,14,15,16 Ethernet4/1 4
+Ethernet16 21,22,23,24 Ethernet5/1 5
+Ethernet20 17,18,19,20 Ethernet6/1 6
+Ethernet24 25,26,27,28 Ethernet7/1 7
+Ethernet28 29,30,31,32 Ethernet8/1 8
+Ethernet32 37,38,39,40 Ethernet9/1 9
+Ethernet36 33,34,35,36 Ethernet10/1 10
+Ethernet40 41,42,43,44 Ethernet11/1 11
+Ethernet44 45,46,47,48 Ethernet12/1 12
+Ethernet48 53,54,55,56 Ethernet13/1 13
+Ethernet52 49,50,51,52 Ethernet14/1 14
+Ethernet56 57,58,59,60 Ethernet15/1 15
+Ethernet60 61,62,63,64 Ethernet16/1 16
+Ethernet64 69,70,71,72 Ethernet17/1 17
+Ethernet68 65,66,67,68 Ethernet18/1 18
+Ethernet72 73,74,75,76 Ethernet19/1 19
+Ethernet76 77,78,79,80 Ethernet20/1 20
+Ethernet80 85,86,87,88 Ethernet21/1 21
+Ethernet84 81,82,83,84 Ethernet22/1 22
+Ethernet88 89,90,91,92 Ethernet23/1 23
+Ethernet92 93,94,95,96 Ethernet24/1 24
+Ethernet96 101,102,103,104 Ethernet25/1 25
+Ethernet100 97,98,99,100 Ethernet26/1 26
+Ethernet104 105,106,107,108 Ethernet27/1 27
+Ethernet108 109,110,111,112 Ethernet28/1 28
+Ethernet112 117,118,119,120 Ethernet29/1 29
+Ethernet116 113,114,115,116 Ethernet30/1 30
+Ethernet120 121,122,123,124 Ethernet31/1 31
+Ethernet124 125,126,127,128 Ethernet32/1 32
+Ethernet128 129 Ethernet33 33
+Ethernet132 128 Ethernet34 34
diff --git a/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/sai.profile b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/sai.profile
new file mode 100644
index 000000000000..d359ffc15cba
--- /dev/null
+++ b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/sai.profile
@@ -0,0 +1 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-a7050cx3-32s-32x100G.config.bcm
diff --git a/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/td3-a7050cx3-32s-32x100G.config.bcm b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/td3-a7050cx3-32s-32x100G.config.bcm
new file mode 100644
index 000000000000..217d15b4e579
--- /dev/null
+++ b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/td3-a7050cx3-32s-32x100G.config.bcm
@@ -0,0 +1,503 @@
+arl_clean_timeout_usec=15000000
+asf_mem_profile=2
+bcm_num_cos=8
+bcm_stat_flags=1
+bcm_stat_jumbo=9236
+bcm_tunnel_term_compatible_mode=1
+cdma_timeout_usec=15000000
+core_clock_frequency=1525
+dma_desc_timeout_usec=15000000
+dpp_clock_ratio=2:3
+fpem_mem_entries=0
+higig2_hdr_mode=1
+ifp_inports_support_enable=1
+ipv6_lpm_128b_enable=1
+l2_mem_entries=32768
+l2xmsg_mode=1
+l3_alpm_enable=2
+l3_max_ecmp_mode=1
+l3_mem_entries=16384
+max_vp_lags=0
+miim_intr_enable=0
+module_64ports=1
+multicast_l2_range=16383
+multicast_l3_range=0
+os=unix
+oversubscribe_mode=1
+pbmp_xport_xe=0x4888888888888888c2222222222222222
+PHY_AN_ALLOW_PLL_CHANGE=1
+phy_an_c37_130=2
+phy_an_c37_66=2
+phy_an_c73=1
+port_flex_enable=1
+port_init_autoneg=0
+port_phy_addr=0xff
+robust_hash_disable_egress_vlan=1
+robust_hash_disable_mpls=1
+robust_hash_disable_vlan=1
+sram_scan_enable=0
+stable_size=0x5500000
+tdma_timeout_usec=15000000
+tslam_timeout_usec=15000000
+phy_chain_rx_lane_map_physical{1.0}=0x1302
+phy_chain_rx_lane_map_physical{101.0}=0x0213
+phy_chain_rx_lane_map_physical{105.0}=0x2031
+phy_chain_rx_lane_map_physical{109.0}=0x0213
+phy_chain_rx_lane_map_physical{113.0}=0x2130
+phy_chain_rx_lane_map_physical{117.0}=0x0213
+phy_chain_rx_lane_map_physical{121.0}=0x2031
+phy_chain_rx_lane_map_physical{125.0}=0x0213
+phy_chain_rx_lane_map_physical{129.0}=0x3210
+phy_chain_rx_lane_map_physical{13.0}=0x3120
+phy_chain_rx_lane_map_physical{17.0}=0x1203
+phy_chain_rx_lane_map_physical{21.0}=0x3120
+phy_chain_rx_lane_map_physical{25.0}=0x3120
+phy_chain_rx_lane_map_physical{29.0}=0x3120
+phy_chain_rx_lane_map_physical{33.0}=0x1203
+phy_chain_rx_lane_map_physical{37.0}=0x3120
+phy_chain_rx_lane_map_physical{41.0}=0x3120
+phy_chain_rx_lane_map_physical{45.0}=0x3120
+phy_chain_rx_lane_map_physical{49.0}=0x1203
+phy_chain_rx_lane_map_physical{5.0}=0x3120
+phy_chain_rx_lane_map_physical{53.0}=0x3120
+phy_chain_rx_lane_map_physical{57.0}=0x3120
+phy_chain_rx_lane_map_physical{61.0}=0x3120
+phy_chain_rx_lane_map_physical{65.0}=0x2130
+phy_chain_rx_lane_map_physical{69.0}=0x0213
+phy_chain_rx_lane_map_physical{73.0}=0x2031
+phy_chain_rx_lane_map_physical{77.0}=0x0213
+phy_chain_rx_lane_map_physical{81.0}=0x2130
+phy_chain_rx_lane_map_physical{85.0}=0x0213
+phy_chain_rx_lane_map_physical{89.0}=0x2031
+phy_chain_rx_lane_map_physical{9.0}=0x3120
+phy_chain_rx_lane_map_physical{93.0}=0x0213
+phy_chain_rx_lane_map_physical{97.0}=0x2130
+phy_chain_rx_polarity_flip_physical{100.0}=0x1
+phy_chain_rx_polarity_flip_physical{10.0}=0x0
+phy_chain_rx_polarity_flip_physical{1.0}=0x0
+phy_chain_rx_polarity_flip_physical{101.0}=0x1
+phy_chain_rx_polarity_flip_physical{102.0}=0x0
+phy_chain_rx_polarity_flip_physical{103.0}=0x0
+phy_chain_rx_polarity_flip_physical{104.0}=0x1
+phy_chain_rx_polarity_flip_physical{105.0}=0x1
+phy_chain_rx_polarity_flip_physical{106.0}=0x1
+phy_chain_rx_polarity_flip_physical{107.0}=0x1
+phy_chain_rx_polarity_flip_physical{108.0}=0x0
+phy_chain_rx_polarity_flip_physical{109.0}=0x0
+phy_chain_rx_polarity_flip_physical{110.0}=0x0
+phy_chain_rx_polarity_flip_physical{11.0}=0x1
+phy_chain_rx_polarity_flip_physical{111.0}=0x1
+phy_chain_rx_polarity_flip_physical{112.0}=0x1
+phy_chain_rx_polarity_flip_physical{113.0}=0x1
+phy_chain_rx_polarity_flip_physical{114.0}=0x1
+phy_chain_rx_polarity_flip_physical{115.0}=0x0
+phy_chain_rx_polarity_flip_physical{116.0}=0x1
+phy_chain_rx_polarity_flip_physical{117.0}=0x0
+phy_chain_rx_polarity_flip_physical{118.0}=0x0
+phy_chain_rx_polarity_flip_physical{119.0}=0x1
+phy_chain_rx_polarity_flip_physical{120.0}=0x1
+phy_chain_rx_polarity_flip_physical{12.0}=0x1
+phy_chain_rx_polarity_flip_physical{121.0}=0x1
+phy_chain_rx_polarity_flip_physical{122.0}=0x1
+phy_chain_rx_polarity_flip_physical{123.0}=0x1
+phy_chain_rx_polarity_flip_physical{124.0}=0x0
+phy_chain_rx_polarity_flip_physical{125.0}=0x0
+phy_chain_rx_polarity_flip_physical{126.0}=0x0
+phy_chain_rx_polarity_flip_physical{127.0}=0x1
+phy_chain_rx_polarity_flip_physical{128.0}=0x1
+phy_chain_rx_polarity_flip_physical{129.0}=0x0
+phy_chain_rx_polarity_flip_physical{13.0}=0x1
+phy_chain_rx_polarity_flip_physical{131.0}=0x0
+phy_chain_rx_polarity_flip_physical{14.0}=0x1
+phy_chain_rx_polarity_flip_physical{15.0}=0x0
+phy_chain_rx_polarity_flip_physical{16.0}=0x0
+phy_chain_rx_polarity_flip_physical{17.0}=0x0
+phy_chain_rx_polarity_flip_physical{18.0}=0x0
+phy_chain_rx_polarity_flip_physical{19.0}=0x1
+phy_chain_rx_polarity_flip_physical{20.0}=0x0
+phy_chain_rx_polarity_flip_physical{2.0}=0x0
+phy_chain_rx_polarity_flip_physical{21.0}=0x1
+phy_chain_rx_polarity_flip_physical{22.0}=0x1
+phy_chain_rx_polarity_flip_physical{23.0}=0x0
+phy_chain_rx_polarity_flip_physical{24.0}=0x0
+phy_chain_rx_polarity_flip_physical{25.0}=0x0
+phy_chain_rx_polarity_flip_physical{26.0}=0x1
+phy_chain_rx_polarity_flip_physical{27.0}=0x1
+phy_chain_rx_polarity_flip_physical{28.0}=0x0
+phy_chain_rx_polarity_flip_physical{29.0}=0x1
+phy_chain_rx_polarity_flip_physical{30.0}=0x1
+phy_chain_rx_polarity_flip_physical{3.0}=0x0
+phy_chain_rx_polarity_flip_physical{31.0}=0x0
+phy_chain_rx_polarity_flip_physical{32.0}=0x0
+phy_chain_rx_polarity_flip_physical{33.0}=0x0
+phy_chain_rx_polarity_flip_physical{34.0}=0x0
+phy_chain_rx_polarity_flip_physical{35.0}=0x1
+phy_chain_rx_polarity_flip_physical{36.0}=0x0
+phy_chain_rx_polarity_flip_physical{37.0}=0x1
+phy_chain_rx_polarity_flip_physical{38.0}=0x1
+phy_chain_rx_polarity_flip_physical{39.0}=0x0
+phy_chain_rx_polarity_flip_physical{40.0}=0x0
+phy_chain_rx_polarity_flip_physical{4.0}=0x1
+phy_chain_rx_polarity_flip_physical{41.0}=0x0
+phy_chain_rx_polarity_flip_physical{42.0}=0x0
+phy_chain_rx_polarity_flip_physical{43.0}=0x1
+phy_chain_rx_polarity_flip_physical{44.0}=0x1
+phy_chain_rx_polarity_flip_physical{45.0}=0x1
+phy_chain_rx_polarity_flip_physical{46.0}=0x1
+phy_chain_rx_polarity_flip_physical{47.0}=0x0
+phy_chain_rx_polarity_flip_physical{48.0}=0x0
+phy_chain_rx_polarity_flip_physical{49.0}=0x0
+phy_chain_rx_polarity_flip_physical{50.0}=0x0
+phy_chain_rx_polarity_flip_physical{5.0}=0x0
+phy_chain_rx_polarity_flip_physical{51.0}=0x1
+phy_chain_rx_polarity_flip_physical{52.0}=0x0
+phy_chain_rx_polarity_flip_physical{53.0}=0x1
+phy_chain_rx_polarity_flip_physical{54.0}=0x1
+phy_chain_rx_polarity_flip_physical{55.0}=0x0
+phy_chain_rx_polarity_flip_physical{56.0}=0x0
+phy_chain_rx_polarity_flip_physical{57.0}=0x0
+phy_chain_rx_polarity_flip_physical{58.0}=0x0
+phy_chain_rx_polarity_flip_physical{59.0}=0x1
+phy_chain_rx_polarity_flip_physical{60.0}=0x1
+phy_chain_rx_polarity_flip_physical{6.0}=0x1
+phy_chain_rx_polarity_flip_physical{61.0}=0x1
+phy_chain_rx_polarity_flip_physical{62.0}=0x1
+phy_chain_rx_polarity_flip_physical{63.0}=0x0
+phy_chain_rx_polarity_flip_physical{64.0}=0x0
+phy_chain_rx_polarity_flip_physical{65.0}=0x1
+phy_chain_rx_polarity_flip_physical{66.0}=0x1
+phy_chain_rx_polarity_flip_physical{67.0}=0x0
+phy_chain_rx_polarity_flip_physical{68.0}=0x1
+phy_chain_rx_polarity_flip_physical{69.0}=0x0
+phy_chain_rx_polarity_flip_physical{70.0}=0x0
+phy_chain_rx_polarity_flip_physical{7.0}=0x0
+phy_chain_rx_polarity_flip_physical{71.0}=0x1
+phy_chain_rx_polarity_flip_physical{72.0}=0x1
+phy_chain_rx_polarity_flip_physical{73.0}=0x1
+phy_chain_rx_polarity_flip_physical{74.0}=0x1
+phy_chain_rx_polarity_flip_physical{75.0}=0x1
+phy_chain_rx_polarity_flip_physical{76.0}=0x0
+phy_chain_rx_polarity_flip_physical{77.0}=0x0
+phy_chain_rx_polarity_flip_physical{78.0}=0x0
+phy_chain_rx_polarity_flip_physical{79.0}=0x1
+phy_chain_rx_polarity_flip_physical{80.0}=0x1
+phy_chain_rx_polarity_flip_physical{8.0}=0x0
+phy_chain_rx_polarity_flip_physical{81.0}=0x1
+phy_chain_rx_polarity_flip_physical{82.0}=0x1
+phy_chain_rx_polarity_flip_physical{83.0}=0x0
+phy_chain_rx_polarity_flip_physical{84.0}=0x1
+phy_chain_rx_polarity_flip_physical{85.0}=0x0
+phy_chain_rx_polarity_flip_physical{86.0}=0x0
+phy_chain_rx_polarity_flip_physical{87.0}=0x1
+phy_chain_rx_polarity_flip_physical{88.0}=0x1
+phy_chain_rx_polarity_flip_physical{89.0}=0x1
+phy_chain_rx_polarity_flip_physical{90.0}=0x1
+phy_chain_rx_polarity_flip_physical{9.0}=0x0
+phy_chain_rx_polarity_flip_physical{91.0}=0x1
+phy_chain_rx_polarity_flip_physical{92.0}=0x0
+phy_chain_rx_polarity_flip_physical{93.0}=0x0
+phy_chain_rx_polarity_flip_physical{94.0}=0x0
+phy_chain_rx_polarity_flip_physical{95.0}=0x1
+phy_chain_rx_polarity_flip_physical{96.0}=0x1
+phy_chain_rx_polarity_flip_physical{97.0}=0x1
+phy_chain_rx_polarity_flip_physical{98.0}=0x1
+phy_chain_rx_polarity_flip_physical{99.0}=0x0
+phy_chain_tx_lane_map_physical{1.0}=0x3021
+phy_chain_tx_lane_map_physical{101.0}=0x3120
+phy_chain_tx_lane_map_physical{105.0}=0x1302
+phy_chain_tx_lane_map_physical{109.0}=0x2130
+phy_chain_tx_lane_map_physical{113.0}=0x1302
+phy_chain_tx_lane_map_physical{117.0}=0x3120
+phy_chain_tx_lane_map_physical{121.0}=0x1302
+phy_chain_tx_lane_map_physical{125.0}=0x3120
+phy_chain_tx_lane_map_physical{129.0}=0x3210
+phy_chain_tx_lane_map_physical{13.0}=0x0213
+phy_chain_tx_lane_map_physical{17.0}=0x2031
+phy_chain_tx_lane_map_physical{21.0}=0x0213
+phy_chain_tx_lane_map_physical{25.0}=0x2031
+phy_chain_tx_lane_map_physical{29.0}=0x1203
+phy_chain_tx_lane_map_physical{33.0}=0x2031
+phy_chain_tx_lane_map_physical{37.0}=0x0213
+phy_chain_tx_lane_map_physical{41.0}=0x2031
+phy_chain_tx_lane_map_physical{45.0}=0x1203
+phy_chain_tx_lane_map_physical{49.0}=0x2031
+phy_chain_tx_lane_map_physical{5.0}=0x1203
+phy_chain_tx_lane_map_physical{53.0}=0x0213
+phy_chain_tx_lane_map_physical{57.0}=0x2031
+phy_chain_tx_lane_map_physical{61.0}=0x1203
+phy_chain_tx_lane_map_physical{65.0}=0x1302
+phy_chain_tx_lane_map_physical{69.0}=0x1302
+phy_chain_tx_lane_map_physical{73.0}=0x1302
+phy_chain_tx_lane_map_physical{77.0}=0x2130
+phy_chain_tx_lane_map_physical{81.0}=0x1302
+phy_chain_tx_lane_map_physical{85.0}=0x3120
+phy_chain_tx_lane_map_physical{89.0}=0x1302
+phy_chain_tx_lane_map_physical{9.0}=0x0213
+phy_chain_tx_lane_map_physical{93.0}=0x2130
+phy_chain_tx_lane_map_physical{97.0}=0x1302
+phy_chain_tx_polarity_flip_physical{100.0}=0x1
+phy_chain_tx_polarity_flip_physical{10.0}=0x1
+phy_chain_tx_polarity_flip_physical{1.0}=0x1
+phy_chain_tx_polarity_flip_physical{101.0}=0x0
+phy_chain_tx_polarity_flip_physical{102.0}=0x1
+phy_chain_tx_polarity_flip_physical{103.0}=0x1
+phy_chain_tx_polarity_flip_physical{104.0}=0x0
+phy_chain_tx_polarity_flip_physical{105.0}=0x1
+phy_chain_tx_polarity_flip_physical{106.0}=0x0
+phy_chain_tx_polarity_flip_physical{107.0}=0x0
+phy_chain_tx_polarity_flip_physical{108.0}=0x0
+phy_chain_tx_polarity_flip_physical{109.0}=0x1
+phy_chain_tx_polarity_flip_physical{110.0}=0x1
+phy_chain_tx_polarity_flip_physical{11.0}=0x0
+phy_chain_tx_polarity_flip_physical{111.0}=0x0
+phy_chain_tx_polarity_flip_physical{112.0}=0x0
+phy_chain_tx_polarity_flip_physical{113.0}=0x0
+phy_chain_tx_polarity_flip_physical{114.0}=0x0
+phy_chain_tx_polarity_flip_physical{115.0}=0x0
+phy_chain_tx_polarity_flip_physical{116.0}=0x0
+phy_chain_tx_polarity_flip_physical{117.0}=0x1
+phy_chain_tx_polarity_flip_physical{118.0}=0x1
+phy_chain_tx_polarity_flip_physical{119.0}=0x0
+phy_chain_tx_polarity_flip_physical{120.0}=0x0
+phy_chain_tx_polarity_flip_physical{12.0}=0x0
+phy_chain_tx_polarity_flip_physical{121.0}=0x1
+phy_chain_tx_polarity_flip_physical{122.0}=0x0
+phy_chain_tx_polarity_flip_physical{123.0}=0x0
+phy_chain_tx_polarity_flip_physical{124.0}=0x0
+phy_chain_tx_polarity_flip_physical{125.0}=0x1
+phy_chain_tx_polarity_flip_physical{126.0}=0x1
+phy_chain_tx_polarity_flip_physical{127.0}=0x0
+phy_chain_tx_polarity_flip_physical{128.0}=0x0
+phy_chain_tx_polarity_flip_physical{129.0}=0x0
+phy_chain_tx_polarity_flip_physical{13.0}=0x1
+phy_chain_tx_polarity_flip_physical{131.0}=0x0
+phy_chain_tx_polarity_flip_physical{14.0}=0x1
+phy_chain_tx_polarity_flip_physical{15.0}=0x0
+phy_chain_tx_polarity_flip_physical{16.0}=0x1
+phy_chain_tx_polarity_flip_physical{17.0}=0x0
+phy_chain_tx_polarity_flip_physical{18.0}=0x0
+phy_chain_tx_polarity_flip_physical{19.0}=0x0
+phy_chain_tx_polarity_flip_physical{20.0}=0x0
+phy_chain_tx_polarity_flip_physical{2.0}=0x1
+phy_chain_tx_polarity_flip_physical{21.0}=0x1
+phy_chain_tx_polarity_flip_physical{22.0}=0x1
+phy_chain_tx_polarity_flip_physical{23.0}=0x0
+phy_chain_tx_polarity_flip_physical{24.0}=0x0
+phy_chain_tx_polarity_flip_physical{25.0}=0x0
+phy_chain_tx_polarity_flip_physical{26.0}=0x0
+phy_chain_tx_polarity_flip_physical{27.0}=0x1
+phy_chain_tx_polarity_flip_physical{28.0}=0x0
+phy_chain_tx_polarity_flip_physical{29.0}=0x0
+phy_chain_tx_polarity_flip_physical{30.0}=0x0
+phy_chain_tx_polarity_flip_physical{3.0}=0x0
+phy_chain_tx_polarity_flip_physical{31.0}=0x1
+phy_chain_tx_polarity_flip_physical{32.0}=0x1
+phy_chain_tx_polarity_flip_physical{33.0}=0x1
+phy_chain_tx_polarity_flip_physical{34.0}=0x1
+phy_chain_tx_polarity_flip_physical{35.0}=0x1
+phy_chain_tx_polarity_flip_physical{36.0}=0x1
+phy_chain_tx_polarity_flip_physical{37.0}=0x0
+phy_chain_tx_polarity_flip_physical{38.0}=0x0
+phy_chain_tx_polarity_flip_physical{39.0}=0x1
+phy_chain_tx_polarity_flip_physical{40.0}=0x1
+phy_chain_tx_polarity_flip_physical{4.0}=0x0
+phy_chain_tx_polarity_flip_physical{41.0}=0x0
+phy_chain_tx_polarity_flip_physical{42.0}=0x1
+phy_chain_tx_polarity_flip_physical{43.0}=0x1
+phy_chain_tx_polarity_flip_physical{44.0}=0x1
+phy_chain_tx_polarity_flip_physical{45.0}=0x0
+phy_chain_tx_polarity_flip_physical{46.0}=0x0
+phy_chain_tx_polarity_flip_physical{47.0}=0x1
+phy_chain_tx_polarity_flip_physical{48.0}=0x1
+phy_chain_tx_polarity_flip_physical{49.0}=0x1
+phy_chain_tx_polarity_flip_physical{50.0}=0x1
+phy_chain_tx_polarity_flip_physical{5.0}=0x1
+phy_chain_tx_polarity_flip_physical{51.0}=0x1
+phy_chain_tx_polarity_flip_physical{52.0}=0x1
+phy_chain_tx_polarity_flip_physical{53.0}=0x0
+phy_chain_tx_polarity_flip_physical{54.0}=0x0
+phy_chain_tx_polarity_flip_physical{55.0}=0x1
+phy_chain_tx_polarity_flip_physical{56.0}=0x1
+phy_chain_tx_polarity_flip_physical{57.0}=0x0
+phy_chain_tx_polarity_flip_physical{58.0}=0x1
+phy_chain_tx_polarity_flip_physical{59.0}=0x1
+phy_chain_tx_polarity_flip_physical{60.0}=0x1
+phy_chain_tx_polarity_flip_physical{6.0}=0x1
+phy_chain_tx_polarity_flip_physical{61.0}=0x0
+phy_chain_tx_polarity_flip_physical{62.0}=0x0
+phy_chain_tx_polarity_flip_physical{63.0}=0x1
+phy_chain_tx_polarity_flip_physical{64.0}=0x1
+phy_chain_tx_polarity_flip_physical{65.0}=0x1
+phy_chain_tx_polarity_flip_physical{66.0}=0x1
+phy_chain_tx_polarity_flip_physical{67.0}=0x1
+phy_chain_tx_polarity_flip_physical{68.0}=0x1
+phy_chain_tx_polarity_flip_physical{69.0}=0x0
+phy_chain_tx_polarity_flip_physical{70.0}=0x1
+phy_chain_tx_polarity_flip_physical{7.0}=0x0
+phy_chain_tx_polarity_flip_physical{71.0}=0x1
+phy_chain_tx_polarity_flip_physical{72.0}=0x1
+phy_chain_tx_polarity_flip_physical{73.0}=0x0
+phy_chain_tx_polarity_flip_physical{74.0}=0x1
+phy_chain_tx_polarity_flip_physical{75.0}=0x1
+phy_chain_tx_polarity_flip_physical{76.0}=0x1
+phy_chain_tx_polarity_flip_physical{77.0}=0x0
+phy_chain_tx_polarity_flip_physical{78.0}=0x0
+phy_chain_tx_polarity_flip_physical{79.0}=0x1
+phy_chain_tx_polarity_flip_physical{80.0}=0x1
+phy_chain_tx_polarity_flip_physical{8.0}=0x1
+phy_chain_tx_polarity_flip_physical{81.0}=0x1
+phy_chain_tx_polarity_flip_physical{82.0}=0x1
+phy_chain_tx_polarity_flip_physical{83.0}=0x1
+phy_chain_tx_polarity_flip_physical{84.0}=0x1
+phy_chain_tx_polarity_flip_physical{85.0}=0x0
+phy_chain_tx_polarity_flip_physical{86.0}=0x0
+phy_chain_tx_polarity_flip_physical{87.0}=0x1
+phy_chain_tx_polarity_flip_physical{88.0}=0x1
+phy_chain_tx_polarity_flip_physical{89.0}=0x0
+phy_chain_tx_polarity_flip_physical{90.0}=0x1
+phy_chain_tx_polarity_flip_physical{9.0}=0x1
+phy_chain_tx_polarity_flip_physical{91.0}=0x1
+phy_chain_tx_polarity_flip_physical{92.0}=0x1
+phy_chain_tx_polarity_flip_physical{93.0}=0x0
+phy_chain_tx_polarity_flip_physical{94.0}=0x0
+phy_chain_tx_polarity_flip_physical{95.0}=0x1
+phy_chain_tx_polarity_flip_physical{96.0}=0x1
+phy_chain_tx_polarity_flip_physical{97.0}=0x1
+phy_chain_tx_polarity_flip_physical{98.0}=0x1
+phy_chain_tx_polarity_flip_physical{99.0}=0x1
+portmap_103=101:100
+portmap_107=105:100
+portmap_1=1:100
+portmap_111=109:100
+portmap_115=113:100
+portmap_119=117:100
+portmap_123=121:100
+portmap_127=125:100
+portmap_130=128:10:m
+portmap_13=13:100
+portmap_17=17:100
+portmap_21=21:100
+portmap_25=25:100
+portmap_29=29:100
+portmap_33=33:100
+portmap_37=37:100
+portmap_41=41:100
+portmap_45=45:100
+portmap_49=49:100
+portmap_53=53:100
+portmap_5=5:100
+portmap_57=57:100
+portmap_61=61:100
+portmap_66=129:10:m
+portmap_67=65:100
+portmap_71=69:100
+portmap_75=73:100
+portmap_79=77:100
+portmap_83=81:100
+portmap_87=85:100
+portmap_91=89:100
+portmap_95=93:100
+portmap_9=9:100
+portmap_99=97:100
+serdes_core_rx_polarity_flip_physical{101}=0x9
+serdes_core_rx_polarity_flip_physical{105}=0x7
+serdes_core_rx_polarity_flip_physical{109}=0xc
+serdes_core_rx_polarity_flip_physical{1}=0x8
+serdes_core_rx_polarity_flip_physical{113}=0xb
+serdes_core_rx_polarity_flip_physical{117}=0xc
+serdes_core_rx_polarity_flip_physical{121}=0x7
+serdes_core_rx_polarity_flip_physical{125}=0xc
+serdes_core_rx_polarity_flip_physical{129}=0x0
+serdes_core_rx_polarity_flip_physical{13}=0x3
+serdes_core_rx_polarity_flip_physical{17}=0x4
+serdes_core_rx_polarity_flip_physical{21}=0x3
+serdes_core_rx_polarity_flip_physical{25}=0x6
+serdes_core_rx_polarity_flip_physical{29}=0x3
+serdes_core_rx_polarity_flip_physical{33}=0x4
+serdes_core_rx_polarity_flip_physical{37}=0x3
+serdes_core_rx_polarity_flip_physical{41}=0xc
+serdes_core_rx_polarity_flip_physical{45}=0x3
+serdes_core_rx_polarity_flip_physical{49}=0x4
+serdes_core_rx_polarity_flip_physical{5}=0x2
+serdes_core_rx_polarity_flip_physical{53}=0x3
+serdes_core_rx_polarity_flip_physical{57}=0xc
+serdes_core_rx_polarity_flip_physical{61}=0x3
+serdes_core_rx_polarity_flip_physical{65}=0xb
+serdes_core_rx_polarity_flip_physical{69}=0xc
+serdes_core_rx_polarity_flip_physical{73}=0x7
+serdes_core_rx_polarity_flip_physical{77}=0xc
+serdes_core_rx_polarity_flip_physical{81}=0xb
+serdes_core_rx_polarity_flip_physical{85}=0xc
+serdes_core_rx_polarity_flip_physical{89}=0x7
+serdes_core_rx_polarity_flip_physical{9}=0xc
+serdes_core_rx_polarity_flip_physical{93}=0xc
+serdes_core_rx_polarity_flip_physical{97}=0xb
+serdes_core_tx_polarity_flip_physical{101}=0x6
+serdes_core_tx_polarity_flip_physical{105}=0x1
+serdes_core_tx_polarity_flip_physical{109}=0x3
+serdes_core_tx_polarity_flip_physical{1}=0x3
+serdes_core_tx_polarity_flip_physical{113}=0x0
+serdes_core_tx_polarity_flip_physical{117}=0x3
+serdes_core_tx_polarity_flip_physical{121}=0x1
+serdes_core_tx_polarity_flip_physical{125}=0x3
+serdes_core_tx_polarity_flip_physical{129}=0x0
+serdes_core_tx_polarity_flip_physical{13}=0xb
+serdes_core_tx_polarity_flip_physical{17}=0x0
+serdes_core_tx_polarity_flip_physical{21}=0x3
+serdes_core_tx_polarity_flip_physical{25}=0x4
+serdes_core_tx_polarity_flip_physical{29}=0xc
+serdes_core_tx_polarity_flip_physical{33}=0xf
+serdes_core_tx_polarity_flip_physical{37}=0xc
+serdes_core_tx_polarity_flip_physical{41}=0xe
+serdes_core_tx_polarity_flip_physical{45}=0xc
+serdes_core_tx_polarity_flip_physical{49}=0xf
+serdes_core_tx_polarity_flip_physical{5}=0xb
+serdes_core_tx_polarity_flip_physical{53}=0xc
+serdes_core_tx_polarity_flip_physical{57}=0xe
+serdes_core_tx_polarity_flip_physical{61}=0xc
+serdes_core_tx_polarity_flip_physical{65}=0xf
+serdes_core_tx_polarity_flip_physical{69}=0xe
+serdes_core_tx_polarity_flip_physical{73}=0xe
+serdes_core_tx_polarity_flip_physical{77}=0xc
+serdes_core_tx_polarity_flip_physical{81}=0xf
+serdes_core_tx_polarity_flip_physical{85}=0xc
+serdes_core_tx_polarity_flip_physical{89}=0xe
+serdes_core_tx_polarity_flip_physical{9}=0x3
+serdes_core_tx_polarity_flip_physical{93}=0xc
+serdes_core_tx_polarity_flip_physical{97}=0xf
+serdes_preemphasis_1=0x14410a
+serdes_preemphasis_5=0x14410a
+serdes_preemphasis_9=0x14410a
+serdes_preemphasis_13=0x14410a
+serdes_preemphasis_17=0x14410a
+serdes_preemphasis_21=0x14410a
+serdes_preemphasis_25=0x14410a
+serdes_preemphasis_29=0x14410a
+serdes_preemphasis_33=0x14410a
+serdes_preemphasis_37=0x14410a
+serdes_preemphasis_41=0x14410a
+serdes_preemphasis_45=0x14410a
+serdes_preemphasis_49=0xf5005
+serdes_preemphasis_53=0xf5005
+serdes_preemphasis_57=0xf5005
+serdes_preemphasis_61=0xf5005
+serdes_driver_current_66=0xe
+serdes_preemphasis_66=0x102804
+serdes_preemphasis_67=0xf5005
+serdes_preemphasis_71=0xf5005
+serdes_preemphasis_75=0xf5005
+serdes_preemphasis_79=0xf5005
+serdes_preemphasis_83=0x14410a
+serdes_preemphasis_87=0x14410a
+serdes_preemphasis_91=0x14410a
+serdes_preemphasis_95=0x14410a
+serdes_preemphasis_99=0x14410a
+serdes_preemphasis_103=0x14410a
+serdes_preemphasis_107=0x14410a
+serdes_preemphasis_111=0x14410a
+serdes_preemphasis_115=0x14410a
+serdes_preemphasis_119=0x14410a
+serdes_preemphasis_123=0x14410a
+serdes_preemphasis_127=0x14410a
+serdes_driver_current_130=0xe
+serdes_preemphasis_130=0x102804
diff --git a/device/arista/x86_64-arista_7050cx3_32s/default_sku b/device/arista/x86_64-arista_7050cx3_32s/default_sku
new file mode 100644
index 000000000000..bff7a549cb2c
--- /dev/null
+++ b/device/arista/x86_64-arista_7050cx3_32s/default_sku
@@ -0,0 +1 @@
+Arista-7050CX3-32S-C32 t1
diff --git a/device/arista/x86_64-arista_7050cx3_32s/fancontrol b/device/arista/x86_64-arista_7050cx3_32s/fancontrol
new file mode 100644
index 000000000000..913075f73d12
--- /dev/null
+++ b/device/arista/x86_64-arista_7050cx3_32s/fancontrol
@@ -0,0 +1,10 @@
+INTERVAL=5
+DEVPATH=hwmon4=devices/pci0000:00/0000:00:02.2/0000:02:00.0/i2c-11/11-004c hwmon3=devices/pci0000:00/0000:00:02.2/0000:02:00.0/i2c-2/2-0060
+DEVNAME=hwmon4=max6658 hwmon3=crow_cpld
+FCTEMPS=hwmon3/pwm4=hwmon4/temp1_input hwmon3/pwm3=hwmon4/temp1_input hwmon3/pwm2=hwmon4/temp1_input hwmon3/pwm1=hwmon4/temp1_input
+FCFANS=hwmon3/pwm4=hwmon3/fan4_input hwmon3/pwm3=hwmon3/fan3_input hwmon3/pwm2=hwmon3/fan2_input hwmon3/pwm1=hwmon3/fan1_input
+MINTEMP=hwmon3/pwm4=40 hwmon3/pwm3=40 hwmon3/pwm2=40 hwmon3/pwm1=40
+MINPWM=hwmon3/pwm4=179 hwmon3/pwm3=179 hwmon3/pwm2=179 hwmon3/pwm1=179
+MAXTEMP=hwmon3/pwm4=50 hwmon3/pwm3=50 hwmon3/pwm2=50 hwmon3/pwm1=50
+MINSTART=hwmon3/pwm4=179 hwmon3/pwm3=179 hwmon3/pwm2=179 hwmon3/pwm1=179
+MINSTOP=hwmon3/pwm4=179 hwmon3/pwm3=179 hwmon3/pwm2=179 hwmon3/pwm1=179
diff --git a/device/arista/x86_64-arista_7050cx3_32s/platform_reboot b/device/arista/x86_64-arista_7050cx3_32s/platform_reboot
new file mode 120000
index 000000000000..7f94a49e38b0
--- /dev/null
+++ b/device/arista/x86_64-arista_7050cx3_32s/platform_reboot
@@ -0,0 +1 @@
+../x86_64-arista_common/platform_reboot
\ No newline at end of file
diff --git a/device/arista/x86_64-arista_7050cx3_32s/plugins b/device/arista/x86_64-arista_7050cx3_32s/plugins
new file mode 120000
index 000000000000..789a45fcace9
--- /dev/null
+++ b/device/arista/x86_64-arista_7050cx3_32s/plugins
@@ -0,0 +1 @@
+../x86_64-arista_common/plugins
\ No newline at end of file
diff --git a/device/arista/x86_64-arista_7050cx3_32s/sensors.conf b/device/arista/x86_64-arista_7050cx3_32s/sensors.conf
new file mode 100644
index 000000000000..c63a526124d0
--- /dev/null
+++ b/device/arista/x86_64-arista_7050cx3_32s/sensors.conf
@@ -0,0 +1,39 @@
+# libsensors configuration file for DCS-7050CX3-32S
+# ------------------------------------------------
+#
+
+bus "i2c-2" "SCD 0000:02:00.0 SMBus master 0 bus 0"
+bus "i2c-11" "SCD 0000:02:00.0 SMBus master 1 bus 1"
+bus "i2c-13" "SCD 0000:02:00.0 SMBus master 1 bus 3"
+bus "i2c-14" "SCD 0000:02:00.0 SMBus master 1 bus 4"
+
+chip "k10temp-pci-00c3"
+ label temp1 "Cpu temp sensor"
+
+chip "max6658-i2c-2-4c"
+ label temp1 "Cpu board temp sensor"
+ set temp1_max 75
+ set temp1_crit 80
+
+ label temp2 "Back panel temp sensor"
+ set temp2_max 75
+ set temp2_crit 85
+
+chip "max6658-i2c-11-4c"
+ label temp1 "Board temp sensor"
+ set temp1_max 75
+ set temp1_crit 85
+
+ label temp2 "Front panel temp sensor"
+ set temp2_max 60
+ set temp2_crit 65
+
+chip "pmbus-i2c-13-58"
+ label temp1 "Power supply 1 hotspot sensor"
+ label temp2 "Power supply 1 inlet temp sensor"
+ label temp3 "Power supply 1 sensor"
+
+chip "pmbus-i2c-14-58"
+ label temp1 "Power supply 2 hotspot sensor"
+ label temp2 "Power supply 2 inlet temp sensor"
+ label temp3 "Power supply 2 sensor"
diff --git a/device/arista/x86_64-arista_7060cx2_32s/Arista-7060CX2-32S-C32 b/device/arista/x86_64-arista_7060cx2_32s/Arista-7060CX2-32S-C32
new file mode 120000
index 000000000000..3ba3c5721b19
--- /dev/null
+++ b/device/arista/x86_64-arista_7060cx2_32s/Arista-7060CX2-32S-C32
@@ -0,0 +1 @@
+../x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32
\ No newline at end of file
diff --git a/device/arista/x86_64-arista_7060cx2_32s/default_sku b/device/arista/x86_64-arista_7060cx2_32s/default_sku
new file mode 100644
index 000000000000..fb5071866c25
--- /dev/null
+++ b/device/arista/x86_64-arista_7060cx2_32s/default_sku
@@ -0,0 +1 @@
+Arista-7060CX2-32S-C32 t1
diff --git a/device/arista/x86_64-arista_7060cx2_32s/fancontrol b/device/arista/x86_64-arista_7060cx2_32s/fancontrol
new file mode 120000
index 000000000000..c37f83f5ffb5
--- /dev/null
+++ b/device/arista/x86_64-arista_7060cx2_32s/fancontrol
@@ -0,0 +1 @@
+../x86_64-arista_7060_cx32s/fancontrol
\ No newline at end of file
diff --git a/device/arista/x86_64-arista_7060cx2_32s/platform_reboot b/device/arista/x86_64-arista_7060cx2_32s/platform_reboot
new file mode 120000
index 000000000000..7f94a49e38b0
--- /dev/null
+++ b/device/arista/x86_64-arista_7060cx2_32s/platform_reboot
@@ -0,0 +1 @@
+../x86_64-arista_common/platform_reboot
\ No newline at end of file
diff --git a/device/arista/x86_64-arista_7060cx2_32s/plugins b/device/arista/x86_64-arista_7060cx2_32s/plugins
new file mode 120000
index 000000000000..5fbbf98a6284
--- /dev/null
+++ b/device/arista/x86_64-arista_7060cx2_32s/plugins
@@ -0,0 +1 @@
+../x86_64-arista_common/plugins/
\ No newline at end of file
diff --git a/device/arista/x86_64-arista_7060cx2_32s/sensors.conf b/device/arista/x86_64-arista_7060cx2_32s/sensors.conf
new file mode 120000
index 000000000000..10be0183e3a7
--- /dev/null
+++ b/device/arista/x86_64-arista_7060cx2_32s/sensors.conf
@@ -0,0 +1 @@
+../x86_64-arista_7060_cx32s/sensors.conf
\ No newline at end of file
diff --git a/device/arista/x86_64-arista_7170_32c/Arista-7170-32C-C32/board_lane_map.json b/device/arista/x86_64-arista_7170_32c/Arista-7170-32C-C32/board_lane_map.json
new file mode 100644
index 000000000000..6ab72e55ab47
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32c/Arista-7170-32C-C32/board_lane_map.json
@@ -0,0 +1,1734 @@
+{
+ "board_name": "7170-32C",
+ "enable_debug_log": 0,
+ "board_lane_map_entry": [
+ {
+ "connector": 1,
+ "device_id": 0,
+ "mac_block": 14,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 2,
+ "device_id": 0,
+ "mac_block": 12,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 3,
+ "device_id": 0,
+ "mac_block": 10,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 4,
+ "device_id": 0,
+ "mac_block": 8,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 5,
+ "device_id": 0,
+ "mac_block": 6,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 6,
+ "device_id": 0,
+ "mac_block": 4,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 7,
+ "device_id": 0,
+ "mac_block": 2,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 8,
+ "device_id": 0,
+ "mac_block": 0,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 9,
+ "device_id": 0,
+ "mac_block": 62,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 10,
+ "device_id": 0,
+ "mac_block": 60,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 11,
+ "device_id": 0,
+ "mac_block": 58,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 12,
+ "device_id": 0,
+ "mac_block": 56,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 13,
+ "device_id": 0,
+ "mac_block": 54,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 14,
+ "device_id": 0,
+ "mac_block": 52,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 15,
+ "device_id": 0,
+ "mac_block": 50,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 16,
+ "device_id": 0,
+ "mac_block": 48,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 17,
+ "device_id": 0,
+ "mac_block": 46,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 18,
+ "device_id": 0,
+ "mac_block": 44,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 19,
+ "device_id": 0,
+ "mac_block": 42,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 20,
+ "device_id": 0,
+ "mac_block": 40,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 21,
+ "device_id": 0,
+ "mac_block": 38,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 22,
+ "device_id": 0,
+ "mac_block": 36,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 23,
+ "device_id": 0,
+ "mac_block": 34,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 24,
+ "device_id": 0,
+ "mac_block": 32,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 25,
+ "device_id": 0,
+ "mac_block": 30,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 26,
+ "device_id": 0,
+ "mac_block": 28,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 27,
+ "device_id": 0,
+ "mac_block": 26,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 28,
+ "device_id": 0,
+ "mac_block": 24,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 29,
+ "device_id": 0,
+ "mac_block": 22,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 30,
+ "device_id": 0,
+ "mac_block": 20,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 31,
+ "device_id": 0,
+ "mac_block": 18,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 32,
+ "device_id": 0,
+ "mac_block": 16,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ }
+ ]
+}
diff --git a/device/arista/x86_64-arista_7170_32c/Arista-7170-32C-C32/port_config.ini b/device/arista/x86_64-arista_7170_32c/Arista-7170-32C-C32/port_config.ini
new file mode 100644
index 000000000000..d983617f1891
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32c/Arista-7170-32C-C32/port_config.ini
@@ -0,0 +1,33 @@
+# name lanes alias speed index
+Ethernet0 0,1,2,3 Ethernet1/1 100000 1
+Ethernet4 4,5,6,7 Ethernet2/1 100000 2
+Ethernet8 8,9,10,11 Ethernet3/1 100000 3
+Ethernet12 12,13,14,15 Ethernet4/1 100000 4
+Ethernet16 16,17,18,19 Ethernet5/1 100000 5
+Ethernet20 20,21,22,23 Ethernet6/1 100000 6
+Ethernet24 24,25,26,27 Ethernet7/1 100000 7
+Ethernet28 28,29,30,31 Ethernet8/1 100000 8
+Ethernet32 32,33,34,35 Ethernet9/1 100000 9
+Ethernet36 36,37,38,39 Ethernet10/1 100000 10
+Ethernet40 40,41,42,43 Ethernet11/1 100000 11
+Ethernet44 44,45,46,47 Ethernet12/1 100000 12
+Ethernet48 48,49,50,51 Ethernet13/1 100000 13
+Ethernet52 52,53,54,55 Ethernet14/1 100000 14
+Ethernet56 56,57,58,59 Ethernet15/1 100000 15
+Ethernet60 60,61,62,63 Ethernet16/1 100000 16
+Ethernet64 64,65,66,67 Ethernet17/1 100000 17
+Ethernet68 68,69,70,71 Ethernet18/1 100000 18
+Ethernet72 72,73,74,75 Ethernet19/1 100000 19
+Ethernet76 76,77,78,79 Ethernet20/1 100000 20
+Ethernet80 80,81,82,83 Ethernet21/1 100000 21
+Ethernet84 84,85,86,87 Ethernet22/1 100000 22
+Ethernet88 88,89,90,91 Ethernet23/1 100000 23
+Ethernet92 92,93,94,95 Ethernet24/1 100000 24
+Ethernet96 96,97,98,99 Ethernet25/1 100000 25
+Ethernet100 100,101,102,103 Ethernet26/1 100000 26
+Ethernet104 104,105,106,107 Ethernet27/1 100000 27
+Ethernet108 108,109,110,111 Ethernet28/1 100000 28
+Ethernet112 112,113,114,115 Ethernet29/1 100000 29
+Ethernet116 116,117,118,119 Ethernet30/1 100000 30
+Ethernet120 120,121,122,123 Ethernet31/1 100000 31
+Ethernet124 124,125,126,127 Ethernet32/1 100000 32
diff --git a/device/arista/x86_64-arista_7170_32c/Arista-7170-32C-C32/switch-sai.conf b/device/arista/x86_64-arista_7170_32c/Arista-7170-32C-C32/switch-sai.conf
new file mode 100644
index 000000000000..0a807b1c9ea7
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32c/Arista-7170-32C-C32/switch-sai.conf
@@ -0,0 +1,33 @@
+{
+ "chip_list": [
+ {
+ "id": "asic-0",
+ "chip_family": "Tofino",
+ "instance": 0,
+ "pcie_sysfs_prefix": "/sys/devices/pci0000:00/0000:00:1c.4/0000:07:00.0",
+ "pcie_domain": 0,
+ "pcie_bus": 7,
+ "pcie_fn": 0,
+ "pcie_dev": 0,
+ "pcie_int_mode": 1,
+ "sds_fw_path": "share/tofino_sds_fw/avago/firmware"
+ }
+ ],
+ "instance": 0,
+ "p4_program_list": [
+ {
+ "id": "pgm-0",
+ "instance": 0,
+ "path": "switch",
+ "program-name": "switch",
+ "pd": "lib/tofinopd/switch/libpd.so",
+ "pd-thrift": "lib/tofinopd/switch/libpdthrift.so",
+ "table-config": "share/tofinopd/switch/context.json",
+ "tofino-bin": "share/tofinopd/switch/tofino.bin",
+ "switchapi": "lib/libswitchapi.so",
+ "sai": "lib/libsai.so",
+ "switchapi_port_add": false,
+ "non_default_port_ppgs": 5
+ }
+ ]
+}
diff --git a/device/arista/x86_64-arista_7170_32c/Arista-7170-32C-C32/switch-tna-sai.conf b/device/arista/x86_64-arista_7170_32c/Arista-7170-32C-C32/switch-tna-sai.conf
new file mode 100644
index 000000000000..ece3fcbe6a90
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32c/Arista-7170-32C-C32/switch-tna-sai.conf
@@ -0,0 +1,39 @@
+{
+ "instance": 0,
+ "chip_list": [
+ {
+ "id": "asic-0",
+ "chip_family": "Tofino",
+ "instance": 0,
+ "pcie_sysfs_prefix": "/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0",
+ "pcie_domain": 0,
+ "pcie_bus": 5,
+ "pcie_fn": 0,
+ "pcie_dev": 0,
+ "pcie_int_mode": 1,
+ "sds_fw_path": "share/tofino_sds_fw/avago/firmware"
+ }
+ ],
+ "p4_devices": [
+ {
+ "device-id": 0,
+ "p4_programs": [
+ {
+ "p4_pipelines": [
+ {
+ "p4_pipeline_name": "pipe",
+ "config": "share/switch/pipe/tofino.bin",
+ "context": "share/switch/pipe/context.json"
+ }
+ ],
+ "program-name": "switch",
+ "sai": "lib/libsai.so",
+ "bfrt-config": "share/switch/bf-rt.json",
+ "model_json_path" : "share/switch/aug_model.json",
+ "switchapi_port_add": false,
+ "non_default_port_ppgs": 5
+ }
+ ]
+ }
+ ]
+}
diff --git a/device/arista/x86_64-arista_7170_32c/default_sku b/device/arista/x86_64-arista_7170_32c/default_sku
new file mode 100644
index 000000000000..536bad44f086
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32c/default_sku
@@ -0,0 +1 @@
+Arista-7170-32CD-C32 t1
diff --git a/device/arista/x86_64-arista_7170_32c/platform_reboot b/device/arista/x86_64-arista_7170_32c/platform_reboot
new file mode 120000
index 000000000000..7f94a49e38b0
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32c/platform_reboot
@@ -0,0 +1 @@
+../x86_64-arista_common/platform_reboot
\ No newline at end of file
diff --git a/device/arista/x86_64-arista_7170_32c/plugins b/device/arista/x86_64-arista_7170_32c/plugins
new file mode 120000
index 000000000000..789a45fcace9
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32c/plugins
@@ -0,0 +1 @@
+../x86_64-arista_common/plugins
\ No newline at end of file
diff --git a/device/arista/x86_64-arista_7170_32c/sensors.conf b/device/arista/x86_64-arista_7170_32c/sensors.conf
new file mode 120000
index 000000000000..1ab9e0f47704
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32c/sensors.conf
@@ -0,0 +1 @@
+../x86_64-arista_7170_64c/sensors.conf
\ No newline at end of file
diff --git a/device/arista/x86_64-arista_7170_32cd/Arista-7170-32CD-C32/board_lane_map.json b/device/arista/x86_64-arista_7170_32cd/Arista-7170-32CD-C32/board_lane_map.json
new file mode 100644
index 000000000000..58a78c5fc4c9
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32cd/Arista-7170-32CD-C32/board_lane_map.json
@@ -0,0 +1,1734 @@
+{
+ "board_name": "7170-32CD",
+ "enable_debug_log": 0,
+ "board_lane_map_entry": [
+ {
+ "connector": 1,
+ "device_id": 0,
+ "mac_block": 7,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 2,
+ "device_id": 0,
+ "mac_block": 6,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 3,
+ "device_id": 0,
+ "mac_block": 5,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 4,
+ "device_id": 0,
+ "mac_block": 4,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 5,
+ "device_id": 0,
+ "mac_block": 3,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 6,
+ "device_id": 0,
+ "mac_block": 2,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 7,
+ "device_id": 0,
+ "mac_block": 1,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 8,
+ "device_id": 0,
+ "mac_block": 0,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 9,
+ "device_id": 0,
+ "mac_block": 31,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 10,
+ "device_id": 0,
+ "mac_block": 30,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 11,
+ "device_id": 0,
+ "mac_block": 29,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 12,
+ "device_id": 0,
+ "mac_block": 28,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 13,
+ "device_id": 0,
+ "mac_block": 27,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 14,
+ "device_id": 0,
+ "mac_block": 26,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 15,
+ "device_id": 0,
+ "mac_block": 25,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 16,
+ "device_id": 0,
+ "mac_block": 24,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 17,
+ "device_id": 0,
+ "mac_block": 23,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 18,
+ "device_id": 0,
+ "mac_block": 22,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 19,
+ "device_id": 0,
+ "mac_block": 21,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 20,
+ "device_id": 0,
+ "mac_block": 20,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 21,
+ "device_id": 0,
+ "mac_block": 19,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 22,
+ "device_id": 0,
+ "mac_block": 18,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 23,
+ "device_id": 0,
+ "mac_block": 17,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 24,
+ "device_id": 0,
+ "mac_block": 16,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 25,
+ "device_id": 0,
+ "mac_block": 15,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 26,
+ "device_id": 0,
+ "mac_block": 14,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 27,
+ "device_id": 0,
+ "mac_block": 13,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 28,
+ "device_id": 0,
+ "mac_block": 12,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 29,
+ "device_id": 0,
+ "mac_block": 11,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 30,
+ "device_id": 0,
+ "mac_block": 10,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 31,
+ "device_id": 0,
+ "mac_block": 9,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 1,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 1,
+ "rx_lane": 1,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 0,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 0,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ },
+ {
+ "connector": 32,
+ "device_id": 0,
+ "mac_block": 8,
+ "media_type": "copper",
+ "lane0": {
+ "mac_ch": 0,
+ "tx_lane": 0,
+ "tx_pn_swap": 0,
+ "rx_lane": 0,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane1": {
+ "mac_ch": 1,
+ "tx_lane": 1,
+ "tx_pn_swap": 0,
+ "rx_lane": 1,
+ "rx_pn_swap": 0,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane2": {
+ "mac_ch": 2,
+ "tx_lane": 2,
+ "tx_pn_swap": 1,
+ "rx_lane": 2,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ },
+ "lane3": {
+ "mac_ch": 3,
+ "tx_lane": 3,
+ "tx_pn_swap": 1,
+ "rx_lane": 3,
+ "rx_pn_swap": 1,
+ "serdes_params": {
+ "tx_eq_pre": 2,
+ "tx_eq_post": 4,
+ "tx_eq_attn": 0
+ }
+ }
+ }
+ ]
+}
diff --git a/device/arista/x86_64-arista_7170_32cd/Arista-7170-32CD-C32/port_config.ini b/device/arista/x86_64-arista_7170_32cd/Arista-7170-32CD-C32/port_config.ini
new file mode 100644
index 000000000000..d983617f1891
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32cd/Arista-7170-32CD-C32/port_config.ini
@@ -0,0 +1,33 @@
+# name lanes alias speed index
+Ethernet0 0,1,2,3 Ethernet1/1 100000 1
+Ethernet4 4,5,6,7 Ethernet2/1 100000 2
+Ethernet8 8,9,10,11 Ethernet3/1 100000 3
+Ethernet12 12,13,14,15 Ethernet4/1 100000 4
+Ethernet16 16,17,18,19 Ethernet5/1 100000 5
+Ethernet20 20,21,22,23 Ethernet6/1 100000 6
+Ethernet24 24,25,26,27 Ethernet7/1 100000 7
+Ethernet28 28,29,30,31 Ethernet8/1 100000 8
+Ethernet32 32,33,34,35 Ethernet9/1 100000 9
+Ethernet36 36,37,38,39 Ethernet10/1 100000 10
+Ethernet40 40,41,42,43 Ethernet11/1 100000 11
+Ethernet44 44,45,46,47 Ethernet12/1 100000 12
+Ethernet48 48,49,50,51 Ethernet13/1 100000 13
+Ethernet52 52,53,54,55 Ethernet14/1 100000 14
+Ethernet56 56,57,58,59 Ethernet15/1 100000 15
+Ethernet60 60,61,62,63 Ethernet16/1 100000 16
+Ethernet64 64,65,66,67 Ethernet17/1 100000 17
+Ethernet68 68,69,70,71 Ethernet18/1 100000 18
+Ethernet72 72,73,74,75 Ethernet19/1 100000 19
+Ethernet76 76,77,78,79 Ethernet20/1 100000 20
+Ethernet80 80,81,82,83 Ethernet21/1 100000 21
+Ethernet84 84,85,86,87 Ethernet22/1 100000 22
+Ethernet88 88,89,90,91 Ethernet23/1 100000 23
+Ethernet92 92,93,94,95 Ethernet24/1 100000 24
+Ethernet96 96,97,98,99 Ethernet25/1 100000 25
+Ethernet100 100,101,102,103 Ethernet26/1 100000 26
+Ethernet104 104,105,106,107 Ethernet27/1 100000 27
+Ethernet108 108,109,110,111 Ethernet28/1 100000 28
+Ethernet112 112,113,114,115 Ethernet29/1 100000 29
+Ethernet116 116,117,118,119 Ethernet30/1 100000 30
+Ethernet120 120,121,122,123 Ethernet31/1 100000 31
+Ethernet124 124,125,126,127 Ethernet32/1 100000 32
diff --git a/device/arista/x86_64-arista_7170_32cd/Arista-7170-32CD-C32/switch-sai.conf b/device/arista/x86_64-arista_7170_32cd/Arista-7170-32CD-C32/switch-sai.conf
new file mode 100644
index 000000000000..0a807b1c9ea7
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32cd/Arista-7170-32CD-C32/switch-sai.conf
@@ -0,0 +1,33 @@
+{
+ "chip_list": [
+ {
+ "id": "asic-0",
+ "chip_family": "Tofino",
+ "instance": 0,
+ "pcie_sysfs_prefix": "/sys/devices/pci0000:00/0000:00:1c.4/0000:07:00.0",
+ "pcie_domain": 0,
+ "pcie_bus": 7,
+ "pcie_fn": 0,
+ "pcie_dev": 0,
+ "pcie_int_mode": 1,
+ "sds_fw_path": "share/tofino_sds_fw/avago/firmware"
+ }
+ ],
+ "instance": 0,
+ "p4_program_list": [
+ {
+ "id": "pgm-0",
+ "instance": 0,
+ "path": "switch",
+ "program-name": "switch",
+ "pd": "lib/tofinopd/switch/libpd.so",
+ "pd-thrift": "lib/tofinopd/switch/libpdthrift.so",
+ "table-config": "share/tofinopd/switch/context.json",
+ "tofino-bin": "share/tofinopd/switch/tofino.bin",
+ "switchapi": "lib/libswitchapi.so",
+ "sai": "lib/libsai.so",
+ "switchapi_port_add": false,
+ "non_default_port_ppgs": 5
+ }
+ ]
+}
diff --git a/device/arista/x86_64-arista_7170_32cd/Arista-7170-32CD-C32/switch-tna-sai.conf b/device/arista/x86_64-arista_7170_32cd/Arista-7170-32CD-C32/switch-tna-sai.conf
new file mode 100644
index 000000000000..ece3fcbe6a90
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32cd/Arista-7170-32CD-C32/switch-tna-sai.conf
@@ -0,0 +1,39 @@
+{
+ "instance": 0,
+ "chip_list": [
+ {
+ "id": "asic-0",
+ "chip_family": "Tofino",
+ "instance": 0,
+ "pcie_sysfs_prefix": "/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0",
+ "pcie_domain": 0,
+ "pcie_bus": 5,
+ "pcie_fn": 0,
+ "pcie_dev": 0,
+ "pcie_int_mode": 1,
+ "sds_fw_path": "share/tofino_sds_fw/avago/firmware"
+ }
+ ],
+ "p4_devices": [
+ {
+ "device-id": 0,
+ "p4_programs": [
+ {
+ "p4_pipelines": [
+ {
+ "p4_pipeline_name": "pipe",
+ "config": "share/switch/pipe/tofino.bin",
+ "context": "share/switch/pipe/context.json"
+ }
+ ],
+ "program-name": "switch",
+ "sai": "lib/libsai.so",
+ "bfrt-config": "share/switch/bf-rt.json",
+ "model_json_path" : "share/switch/aug_model.json",
+ "switchapi_port_add": false,
+ "non_default_port_ppgs": 5
+ }
+ ]
+ }
+ ]
+}
diff --git a/device/arista/x86_64-arista_7170_32cd/default_sku b/device/arista/x86_64-arista_7170_32cd/default_sku
new file mode 100644
index 000000000000..536bad44f086
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32cd/default_sku
@@ -0,0 +1 @@
+Arista-7170-32CD-C32 t1
diff --git a/device/arista/x86_64-arista_7170_32cd/platform_reboot b/device/arista/x86_64-arista_7170_32cd/platform_reboot
new file mode 120000
index 000000000000..7f94a49e38b0
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32cd/platform_reboot
@@ -0,0 +1 @@
+../x86_64-arista_common/platform_reboot
\ No newline at end of file
diff --git a/device/arista/x86_64-arista_7170_32cd/plugins b/device/arista/x86_64-arista_7170_32cd/plugins
new file mode 120000
index 000000000000..789a45fcace9
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32cd/plugins
@@ -0,0 +1 @@
+../x86_64-arista_common/plugins
\ No newline at end of file
diff --git a/device/arista/x86_64-arista_7170_32cd/sensors.conf b/device/arista/x86_64-arista_7170_32cd/sensors.conf
new file mode 120000
index 000000000000..1ab9e0f47704
--- /dev/null
+++ b/device/arista/x86_64-arista_7170_32cd/sensors.conf
@@ -0,0 +1 @@
+../x86_64-arista_7170_64c/sensors.conf
\ No newline at end of file
diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/pltfm_mgr_rpc/__init__.py b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/pltfm_mgr_rpc/__init__.py
index 09cb959f2d46..414c3d6389c5 100644
--- a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/pltfm_mgr_rpc/__init__.py
+++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/pltfm_mgr_rpc/__init__.py
@@ -1 +1 @@
-__all__ = ['ttypes', 'constants', 'pltfm_mgr_rpc']
+__all__ = ['ttypes', 'pltfm_mgr_rpc']
diff --git a/device/celestica/x86_64-cel_e1031-r0/pmon_daemon_control.json b/device/celestica/x86_64-cel_e1031-r0/pmon_daemon_control.json
new file mode 100644
index 000000000000..94592fa8cebc
--- /dev/null
+++ b/device/celestica/x86_64-cel_e1031-r0/pmon_daemon_control.json
@@ -0,0 +1,3 @@
+{
+ "skip_ledd": true
+}
diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/chassis.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/chassis.py
index 99eb49ce53e0..719170d831b7 100644
--- a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/chassis.py
+++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/chassis.py
@@ -19,7 +19,6 @@
from sonic_platform.fan import Fan
from sonic_platform.psu import Psu
from sonic_platform.component import Component
- from sonic_platform.watchdog import Watchdog
from sonic_platform.thermal import Thermal
from sonic_platform.sfp import Sfp
from sonic_platform.eeprom import Tlv
@@ -54,7 +53,9 @@ def __init__(self):
for index in range(0, NUM_THERMAL):
thermal = Thermal(index)
self._thermal_list.append(thermal)
- for index in range(0, NUM_SFP):
+ # sfp index start from 1
+ self._sfp_list.append(None)
+ for index in range(1, NUM_SFP+1):
sfp = Sfp(index)
self._sfp_list.append(sfp)
for index in range(0, NUM_COMPONENT):
@@ -63,7 +64,6 @@ def __init__(self):
self._reboot_cause_path = HOST_REBOOT_CAUSE_PATH if self.__is_host(
) else PMON_REBOOT_CAUSE_PATH
- self._watchdog = Watchdog()
self._eeprom = Tlv()
def __is_host(self):
@@ -134,3 +134,16 @@ def get_reboot_cause(self):
description = 'Unknown reason'
return (reboot_cause, description)
+
+ def get_watchdog(self):
+ """
+ Retreives hardware watchdog device on this chassis
+ Returns:
+ An object derived from WatchdogBase representing the hardware
+ watchdog device
+ """
+ if self._watchdog is None:
+ from sonic_platform.watchdog import Watchdog
+ self._watchdog = Watchdog()
+
+ return self._watchdog
diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/component.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/component.py
index ad6810b14c38..fe34bc45c670 100644
--- a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/component.py
+++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/component.py
@@ -140,7 +140,7 @@ def install_firmware(self, image_path):
new_image_path = os.path.join("/tmp", (root.lower() + ext))
shutil.copy(image_path, new_image_path)
install_command = "ispvm %s" % new_image_path
- elif self.name == "BIOS":
- install_command = "afulnx_64 %s /p /b /n /x /r" % image_path
+ # elif self.name == "BIOS":
+ # install_command = "afulnx_64 %s /p /b /n /x /r" % image_path
return self.__run_command(install_command)
diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/sfp.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/sfp.py
index 4cfdcf50b66d..6ef8838ba8af 100644
--- a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/sfp.py
+++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/sfp.py
@@ -94,7 +94,7 @@ class Sfp(SfpBase):
def __init__(self, sfp_index):
# Init index
self.index = sfp_index
- self.port_num = self.index + 1
+ self.port_num = self.index
# Init eeprom path
eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'
diff --git a/device/celestica/x86_64-cel_midstone-r0/pmon_daemon_control.json b/device/celestica/x86_64-cel_midstone-r0/pmon_daemon_control.json
new file mode 100644
index 000000000000..94592fa8cebc
--- /dev/null
+++ b/device/celestica/x86_64-cel_midstone-r0/pmon_daemon_control.json
@@ -0,0 +1,3 @@
+{
+ "skip_ledd": true
+}
diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50-50-40/port_config.ini b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50-50-40/port_config.ini
new file mode 100644
index 000000000000..4bc2ce344039
--- /dev/null
+++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50-50-40/port_config.ini
@@ -0,0 +1,57 @@
+# name lanes alias index speed
+Ethernet0 65,66 Eth1/1 1 50000
+Ethernet2 67,68 Eth1/2 1 50000
+Ethernet4 69,70 Eth2/1 2 50000
+Ethernet6 71,72 Eth2/2 2 50000
+Ethernet8 73,74 Eth3/1 3 50000
+Ethernet10 75,76 Eth3/2 3 50000
+Ethernet12 77,78 Eth4/1 4 50000
+Ethernet14 79,80 Eth4/2 4 50000
+Ethernet16 33,34 Eth5/1 5 50000
+Ethernet18 35,36 Eth5/2 5 50000
+Ethernet20 37,38 Eth6/1 6 50000
+Ethernet22 39,40 Eth6/2 6 50000
+Ethernet24 41,42 Eth7/1 7 50000
+Ethernet26 43,44 Eth7/2 7 50000
+Ethernet28 45,46 Eth8/1 8 50000
+Ethernet30 47,48 Eth8/2 8 50000
+Ethernet32 49,50 Eth9/1 9 50000
+Ethernet34 51,52 Eth9/2 9 50000
+Ethernet36 53,54 Eth10/1 10 50000
+Ethernet38 55,56 Eth10/2 10 50000
+Ethernet40 57,58 Eth11/1 11 50000
+Ethernet42 59,60 Eth11/2 11 50000
+Ethernet44 61,62 Eth12/1 12 50000
+Ethernet46 63,64 Eth12/2 12 50000
+Ethernet48 81,82 Eth13/1 13 50000
+Ethernet50 83,84 Eth13/2 13 50000
+Ethernet52 85,86 Eth14/1 14 50000
+Ethernet54 87,88 Eth14/2 14 50000
+Ethernet56 89,90 Eth15/1 15 50000
+Ethernet58 91,92 Eth15/2 15 50000
+Ethernet60 93,94 Eth16/1 16 50000
+Ethernet62 95,96 Eth16/2 16 50000
+Ethernet64 97,98 Eth17/1 17 50000
+Ethernet66 99,100 Eth17/2 17 50000
+Ethernet68 101,102 Eth18/1 18 50000
+Ethernet70 103,104 Eth18/2 18 50000
+Ethernet72 105,106 Eth19/1 19 50000
+Ethernet74 107,108 Eth19/2 19 50000
+Ethernet76 109,110 Eth20/1 20 50000
+Ethernet78 111,112 Eth20/2 20 50000
+Ethernet80 1,2 Eth21/1 21 50000
+Ethernet82 3,4 Eth21/2 21 50000
+Ethernet84 5,6 Eth22/1 22 50000
+Ethernet86 7,8 Eth22/2 22 50000
+Ethernet88 9,10 Eth23/1 23 50000
+Ethernet90 11,12 Eth23/2 23 50000
+Ethernet92 13,14 Eth24/1 24 50000
+Ethernet94 15,16 Eth24/2 24 50000
+Ethernet96 17,18,19,20 Eth25 25 40000
+Ethernet100 21,22,23,24 Eth26 26 40000
+Ethernet104 25,26,27,28 Eth27 27 40000
+Ethernet108 29,30,31,32 Eth28 28 40000
+Ethernet112 113,114,115,116 Eth29 29 40000
+Ethernet116 117,118,119,120 Eth30 30 40000
+Ethernet120 121,122,123,124 Eth31 31 40000
+Ethernet124 125,126,127,128 Eth32 32 40000
diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50-50-40/sai.profile b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50-50-40/sai.profile
new file mode 100644
index 000000000000..7342ae8002e8
--- /dev/null
+++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50-50-40/sai.profile
@@ -0,0 +1 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/th-seastone-dx010-config-flex-all.bcm
diff --git a/device/celestica/x86_64-cel_seastone-r0/pmon_daemon_control.json b/device/celestica/x86_64-cel_seastone-r0/pmon_daemon_control.json
new file mode 100644
index 000000000000..94592fa8cebc
--- /dev/null
+++ b/device/celestica/x86_64-cel_seastone-r0/pmon_daemon_control.json
@@ -0,0 +1,3 @@
+{
+ "skip_ledd": true
+}
diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py
index c9447b56a2fe..7db46e55bd8c 100644
--- a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py
+++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py
@@ -19,7 +19,6 @@
from sonic_platform.fan import Fan
from sonic_platform.psu import Psu
from sonic_platform.component import Component
- from sonic_platform.watchdog import Watchdog
from sonic_platform.thermal import Thermal
from sonic_platform.sfp import Sfp
from sonic_platform.eeprom import Tlv
@@ -56,14 +55,15 @@ def __init__(self):
for index in range(0, NUM_THERMAL):
thermal = Thermal(index)
self._thermal_list.append(thermal)
- for index in range(0, NUM_SFP):
+ # sfp index start from 1
+ self._sfp_list.append(None)
+ for index in range(1, NUM_SFP+1):
sfp = Sfp(index)
self._sfp_list.append(sfp)
for index in range(0, NUM_COMPONENT):
component = Component(index)
self._component_list.append(component)
- self._watchdog = Watchdog()
self._eeprom = Tlv()
def __is_host(self):
@@ -146,3 +146,16 @@ def get_reboot_cause(self):
description = 'Unknown reason'
return (reboot_cause, description)
+
+ def get_watchdog(self):
+ """
+ Retreives hardware watchdog device on this chassis
+ Returns:
+ An object derived from WatchdogBase representing the hardware
+ watchdog device
+ """
+ if self._watchdog is None:
+ from sonic_platform.watchdog import Watchdog
+ self._watchdog = Watchdog()
+
+ return self._watchdog
diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/component.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/component.py
index 67c7a9c46341..d94a93474452 100644
--- a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/component.py
+++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/component.py
@@ -141,7 +141,7 @@ def install_firmware(self, image_path):
new_image_path = os.path.join("/tmp", (root.lower() + ext))
shutil.copy(image_path, new_image_path)
install_command = "ispvm %s" % new_image_path
- elif self.name == "BIOS":
- install_command = "afulnx_64 %s /p /b /n /x /r" % image_path
+ # elif self.name == "BIOS":
+ # install_command = "afulnx_64 %s /p /b /n /x /r" % image_path
return self.__run_command(install_command)
diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/sfp.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/sfp.py
index 3a02be39df6e..04fb36b72b8f 100644
--- a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/sfp.py
+++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/sfp.py
@@ -100,7 +100,7 @@ class Sfp(SfpBase):
def __init__(self, sfp_index):
# Init index
self.index = sfp_index
- self.port_num = self.index + 1 if self.PORT_START == 1 else index
+ self.port_num = self.index
# Init eeprom path
eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'
diff --git a/device/celestica/x86_64-cel_silverstone-r0/pmon_daemon_control.json b/device/celestica/x86_64-cel_silverstone-r0/pmon_daemon_control.json
new file mode 100644
index 000000000000..94592fa8cebc
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/pmon_daemon_control.json
@@ -0,0 +1,3 @@
+{
+ "skip_ledd": true
+}
diff --git a/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/buffers.json.j2 b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/buffers.json.j2
new file mode 100644
index 000000000000..2c391214fa65
--- /dev/null
+++ b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/buffers.json.j2
@@ -0,0 +1,111 @@
+{# Default values which will be used if no actual configura available #}
+{% set default_cable = '40m' %}
+{% set default_speed = '10G' %}
+{% set default_ports_num = 54 -%}
+
+{# Port configuration to cable length look-up table #}
+{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #}
+{# Roles described in the minigraph #}
+{% set ports2cable = {
+ 'torrouter_server' : '5m',
+ 'leafrouter_torrouter' : '40m',
+ 'spinerouter_leafrouter' : '300m'
+ }
+%}
+
+{%- macro cable_length(port_name) -%}
+ {%- set cable_len = [] -%}
+ {%- for local_port in DEVICE_NEIGHBOR -%}
+ {%- if local_port == port_name -%}
+ {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
+ {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
+ {%- set neighbor_role = neighbor.type -%}
+ {%- set roles1 = switch_role + '_' + neighbor_role %}
+ {%- set roles2 = neighbor_role + '_' + switch_role -%}
+ {%- set roles1 = roles1 | lower -%}
+ {%- set roles2 = roles2 | lower -%}
+ {%- if roles1 in ports2cable -%}
+ {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%}
+ {%- elif roles2 in ports2cable -%}
+ {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%}
+ {%- endif -%}
+ {%- endif -%}
+ {%- endif -%}
+ {%- endfor -%}
+ {%- if cable_len -%}
+ {{ cable_len.0 }}
+ {%- else -%}
+ {{ default_cable }}
+ {%- endif -%}
+{% endmacro %}
+
+{%- if DEVICE_METADATA is defined %}
+{%- set switch_role = DEVICE_METADATA['localhost']['type'] %}
+{%- endif -%}
+
+{# Generate list of ports if not defined #}
+{% if PORT is not defined %}
+ {% set PORT = [] %}
+ {% for port_idx in range(0,default_ports_num) %}
+ {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %}
+ {% endfor %}
+{% endif -%}
+
+{% set port_names_list = [] %}
+{% for port in PORT %}
+ {%- if port_names_list.append(port) %}{% endif %}
+{% endfor %}
+{% set port_names = port_names_list | join(',') -%}
+
+{
+ "CABLE_LENGTH": {
+ "AZURE": {
+ {% for port in PORT %}
+ {% set cable = cable_length(port) -%}
+ "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %}
+
+ {% endfor %}
+ }
+ },
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "20971328",
+ "type": "ingress",
+ "mode": "static"
+ },
+ "ingress_lossy_pool": {
+ "size": "20971328",
+ "type": "ingress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "20971328",
+ "type": "egress",
+ "mode": "static"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossless_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "xon":"78400",
+ "xoff":"132160",
+ "size":"3584",
+ "static_th":"82880"
+ },
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossy_pool]",
+ "size":"3584",
+ "dynamic_th":"-1"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"3584",
+ "dynamic_th":"-4"
+ }
+ },
+ "BUFFER_PG": {
+ },
+ "BUFFER_QUEUE": {
+ }
+}
+
\ No newline at end of file
diff --git a/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/led.bin b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/led.bin
new file mode 100644
index 000000000000..201662a1c605
Binary files /dev/null and b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/led.bin differ
diff --git a/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/pg_profile_lookup.ini b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/pg_profile_lookup.ini
new file mode 100644
index 000000000000..d98b0eca6d19
--- /dev/null
+++ b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/pg_profile_lookup.ini
@@ -0,0 +1,17 @@
+# PG lossless profiles.
+# speed cable size xon xoff threshold
+ 10000 5m 3584 32256 59136 36736
+ 25000 5m 3584 41216 68096 45696
+ 40000 5m 3584 47488 74368 51968
+ 50000 5m 3584 52864 79744 57344
+ 100000 5m 3584 78400 132160 82880
+ 10000 40m 3584 32256 59136 36736
+ 25000 40m 3584 41216 68096 45696
+ 40000 40m 3584 47488 74368 51968
+ 50000 40m 3584 52864 79744 57344
+ 100000 40m 3584 78400 132160 82880
+ 10000 300m 3584 32256 65856 36736
+ 25000 300m 3584 41216 84672 45696
+ 40000 300m 3584 47488 101024 51968
+ 50000 300m 3584 52864 113120 57344
+ 100000 300m 3584 78400 198688 82880
\ No newline at end of file
diff --git a/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/port_config.ini b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/port_config.ini
new file mode 100644
index 000000000000..ab29b7bed9ff
--- /dev/null
+++ b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/port_config.ini
@@ -0,0 +1,55 @@
+# name lanes alias index speed
+Ethernet0 8 Ethernet1/1 1 10000
+Ethernet1 9 Ethernet2/1 2 10000
+Ethernet2 10 Ethernet3/1 3 10000
+Ethernet3 11 Ethernet4/1 4 10000
+Ethernet4 12 Ethernet5/1 5 10000
+Ethernet5 13 Ethernet6/1 6 10000
+Ethernet6 14 Ethernet7/1 7 10000
+Ethernet7 15 Ethernet8/1 8 10000
+Ethernet8 16 Ethernet9/1 9 10000
+Ethernet9 17 Ethernet10/1 10 10000
+Ethernet10 18 Ethernet11/1 11 10000
+Ethernet11 19 Ethernet12/1 12 10000
+Ethernet12 20 Ethernet13/1 13 10000
+Ethernet13 21 Ethernet14/1 14 10000
+Ethernet14 22 Ethernet15/1 15 10000
+Ethernet15 23 Ethernet16/1 16 10000
+Ethernet16 32 Ethernet17/1 17 10000
+Ethernet17 33 Ethernet18/1 18 10000
+Ethernet18 34 Ethernet19/1 19 10000
+Ethernet19 35 Ethernet20/1 20 10000
+Ethernet20 40 Ethernet21/1 21 10000
+Ethernet21 41 Ethernet22/1 22 10000
+Ethernet22 42 Ethernet23/1 23 10000
+Ethernet23 43 Ethernet24/1 24 10000
+Ethernet24 48 Ethernet25/1 25 10000
+Ethernet25 49 Ethernet26/1 26 10000
+Ethernet26 50 Ethernet27/1 27 10000
+Ethernet27 51 Ethernet28/1 28 10000
+Ethernet28 56 Ethernet29/1 29 10000
+Ethernet29 57 Ethernet30/1 30 10000
+Ethernet30 58 Ethernet31/1 31 10000
+Ethernet31 59 Ethernet32/1 32 10000
+Ethernet32 64 Ethernet33/1 33 10000
+Ethernet33 65 Ethernet34/1 34 10000
+Ethernet34 66 Ethernet35/1 35 10000
+Ethernet35 67 Ethernet36/1 36 10000
+Ethernet36 68 Ethernet37/1 37 10000
+Ethernet37 69 Ethernet38/1 38 10000
+Ethernet38 70 Ethernet39/1 39 10000
+Ethernet39 71 Ethernet40/1 40 10000
+Ethernet40 72 Ethernet41/1 41 10000
+Ethernet41 73 Ethernet42/1 42 10000
+Ethernet42 74 Ethernet43/1 43 10000
+Ethernet43 75 Ethernet44/1 44 10000
+Ethernet44 76 Ethernet45/1 45 10000
+Ethernet45 77 Ethernet46/1 46 10000
+Ethernet46 78 Ethernet47/1 47 10000
+Ethernet47 79 Ethernet48/1 48 10000
+Ethernet48 84,85,86,87 Ethernet49/1 49 100000
+Ethernet49 80,81,82,83 Ethernet50/1 50 100000
+Ethernet50 108,109,110,111 Ethernet51/1 51 100000
+Ethernet51 104,105,106,107 Ethernet52/1 52 100000
+Ethernet52 116,117,118,119 Ethernet53/1 53 100000
+Ethernet53 112,113,114,115 Ethernet54/1 54 100000
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.nps.DAC.R0B b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/port_config.nps
old mode 100755
new mode 100644
similarity index 82%
rename from device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.nps.DAC.R0B
rename to device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/port_config.nps
index 857e5f1ede5f..9c6a5af8e5f0
--- a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.nps.DAC.R0B
+++ b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/port_config.nps
@@ -1,60 +1,58 @@
init start stage unit=0 low-level
-init set port-map unit=0 port=0 eth-macro=2 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=1 eth-macro=2 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=2 eth-macro=2 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=3 eth-macro=2 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=4 eth-macro=3 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=5 eth-macro=3 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=6 eth-macro=3 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=7 eth-macro=3 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=8 eth-macro=4 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=9 eth-macro=4 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=10 eth-macro=4 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=11 eth-macro=4 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=12 eth-macro=5 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=13 eth-macro=5 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=14 eth-macro=5 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=15 eth-macro=5 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=16 eth-macro=8 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=17 eth-macro=8 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=18 eth-macro=8 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=19 eth-macro=8 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=20 eth-macro=10 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=21 eth-macro=10 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=22 eth-macro=10 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=23 eth-macro=10 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=24 eth-macro=12 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=25 eth-macro=12 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=26 eth-macro=12 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=27 eth-macro=12 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=28 eth-macro=14 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=29 eth-macro=14 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=30 eth-macro=14 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=31 eth-macro=14 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=32 eth-macro=16 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=33 eth-macro=16 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=34 eth-macro=16 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=35 eth-macro=16 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=36 eth-macro=17 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=37 eth-macro=17 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=38 eth-macro=17 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=39 eth-macro=17 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=40 eth-macro=18 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=41 eth-macro=18 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=42 eth-macro=18 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=43 eth-macro=18 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=44 eth-macro=19 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=45 eth-macro=19 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=46 eth-macro=19 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=47 eth-macro=19 lane=3 max-speed=25g active=true
+init set port-map unit=0 port=0 eth-macro=2 lane=0 max-speed=10g active=true
+init set port-map unit=0 port=1 eth-macro=2 lane=1 max-speed=10g active=true
+init set port-map unit=0 port=2 eth-macro=2 lane=2 max-speed=10g active=true
+init set port-map unit=0 port=3 eth-macro=2 lane=3 max-speed=10g active=true
+init set port-map unit=0 port=4 eth-macro=3 lane=0 max-speed=10g active=true
+init set port-map unit=0 port=5 eth-macro=3 lane=1 max-speed=10g active=true
+init set port-map unit=0 port=6 eth-macro=3 lane=2 max-speed=10g active=true
+init set port-map unit=0 port=7 eth-macro=3 lane=3 max-speed=10g active=true
+init set port-map unit=0 port=8 eth-macro=4 lane=0 max-speed=10g active=true
+init set port-map unit=0 port=9 eth-macro=4 lane=1 max-speed=10g active=true
+init set port-map unit=0 port=10 eth-macro=4 lane=2 max-speed=10g active=true
+init set port-map unit=0 port=11 eth-macro=4 lane=3 max-speed=10g active=true
+init set port-map unit=0 port=12 eth-macro=5 lane=0 max-speed=10g active=true
+init set port-map unit=0 port=13 eth-macro=5 lane=1 max-speed=10g active=true
+init set port-map unit=0 port=14 eth-macro=5 lane=2 max-speed=10g active=true
+init set port-map unit=0 port=15 eth-macro=5 lane=3 max-speed=10g active=true
+init set port-map unit=0 port=16 eth-macro=8 lane=0 max-speed=10g active=true
+init set port-map unit=0 port=17 eth-macro=8 lane=1 max-speed=10g active=true
+init set port-map unit=0 port=18 eth-macro=8 lane=2 max-speed=10g active=true
+init set port-map unit=0 port=19 eth-macro=8 lane=3 max-speed=10g active=true
+init set port-map unit=0 port=20 eth-macro=10 lane=0 max-speed=10g active=true
+init set port-map unit=0 port=21 eth-macro=10 lane=1 max-speed=10g active=true
+init set port-map unit=0 port=22 eth-macro=10 lane=2 max-speed=10g active=true
+init set port-map unit=0 port=23 eth-macro=10 lane=3 max-speed=10g active=true
+init set port-map unit=0 port=24 eth-macro=12 lane=0 max-speed=10g active=true
+init set port-map unit=0 port=25 eth-macro=12 lane=1 max-speed=10g active=true
+init set port-map unit=0 port=26 eth-macro=12 lane=2 max-speed=10g active=true
+init set port-map unit=0 port=27 eth-macro=12 lane=3 max-speed=10g active=true
+init set port-map unit=0 port=28 eth-macro=14 lane=0 max-speed=10g active=true
+init set port-map unit=0 port=29 eth-macro=14 lane=1 max-speed=10g active=true
+init set port-map unit=0 port=30 eth-macro=14 lane=2 max-speed=10g active=true
+init set port-map unit=0 port=31 eth-macro=14 lane=3 max-speed=10g active=true
+init set port-map unit=0 port=32 eth-macro=16 lane=0 max-speed=10g active=true
+init set port-map unit=0 port=33 eth-macro=16 lane=1 max-speed=10g active=true
+init set port-map unit=0 port=34 eth-macro=16 lane=2 max-speed=10g active=true
+init set port-map unit=0 port=35 eth-macro=16 lane=3 max-speed=10g active=true
+init set port-map unit=0 port=36 eth-macro=17 lane=0 max-speed=10g active=true
+init set port-map unit=0 port=37 eth-macro=17 lane=1 max-speed=10g active=true
+init set port-map unit=0 port=38 eth-macro=17 lane=2 max-speed=10g active=true
+init set port-map unit=0 port=39 eth-macro=17 lane=3 max-speed=10g active=true
+init set port-map unit=0 port=40 eth-macro=18 lane=0 max-speed=10g active=true
+init set port-map unit=0 port=41 eth-macro=18 lane=1 max-speed=10g active=true
+init set port-map unit=0 port=42 eth-macro=18 lane=2 max-speed=10g active=true
+init set port-map unit=0 port=43 eth-macro=18 lane=3 max-speed=10g active=true
+init set port-map unit=0 port=44 eth-macro=19 lane=0 max-speed=10g active=true
+init set port-map unit=0 port=45 eth-macro=19 lane=1 max-speed=10g active=true
+init set port-map unit=0 port=46 eth-macro=19 lane=2 max-speed=10g active=true
+init set port-map unit=0 port=47 eth-macro=19 lane=3 max-speed=10g active=true
init set port-map unit=0 port=48 eth-macro=21 lane=0 max-speed=100g active=true
init set port-map unit=0 port=49 eth-macro=20 lane=0 max-speed=100g active=true
-init set port-map unit=0 port=50 eth-macro=23 lane=0 max-speed=100g active=true
-init set port-map unit=0 port=51 eth-macro=22 lane=0 max-speed=100g active=true
-init set port-map unit=0 port=52 eth-macro=27 lane=0 max-speed=100g active=true
-init set port-map unit=0 port=53 eth-macro=26 lane=0 max-speed=100g active=true
-init set port-map unit=0 port=54 eth-macro=29 lane=0 max-speed=100g active=true
-init set port-map unit=0 port=55 eth-macro=28 lane=0 max-speed=100g active=true
+init set port-map unit=0 port=50 eth-macro=27 lane=0 max-speed=100g active=true
+init set port-map unit=0 port=51 eth-macro=26 lane=0 max-speed=100g active=true
+init set port-map unit=0 port=52 eth-macro=29 lane=0 max-speed=100g active=true
+init set port-map unit=0 port=53 eth-macro=28 lane=0 max-speed=100g active=true
init set port-map unit=0 port=129 eth-macro=0 lane=1 max-speed=10g active=true guarantee=true cpi=true
init set port-map unit=0 port=130 eth-macro=0 lane=0 max-speed=10g active=true guarantee=true cpi=true init-done=true
init start stage unit=0 task-rsrc
@@ -110,12 +108,10 @@ phy set lane-swap unit=0 portlist=46 lane-cnt=1 property=tx data=0x2
phy set lane-swap unit=0 portlist=47 lane-cnt=1 property=tx data=0x3
phy set lane-swap unit=0 portlist=48 lane-cnt=4 property=tx data=0x3.0.1.2
phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=tx data=0x3.2.1.0
-phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=tx data=0x0.1.2.3
-phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=tx data=0x3.2.0.1
+phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=tx data=0x3.2.1.0
+phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=52 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=tx data=0x3.2.1.0
-phy set lane-swap unit=0 portlist=54 lane-cnt=4 property=tx data=0x3.2.1.0
-phy set lane-swap unit=0 portlist=55 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=129 lane-cnt=1 property=tx data=0x1
phy set lane-swap unit=0 portlist=130 lane-cnt=1 property=tx data=0x0
phy set lane-swap unit=0 portlist=0 lane-cnt=1 property=rx data=0x0
@@ -168,12 +164,10 @@ phy set lane-swap unit=0 portlist=46 lane-cnt=1 property=rx data=0x0
phy set lane-swap unit=0 portlist=47 lane-cnt=1 property=rx data=0x3
phy set lane-swap unit=0 portlist=48 lane-cnt=4 property=rx data=0x3.1.0.2
phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=rx data=0x3.2.1.0
-phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=rx data=0x3.0.1.2
-phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=rx data=0x3.2.1.0
+phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=rx data=0x1.0.3.2
+phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=rx data=0x2.0.1.3
phy set lane-swap unit=0 portlist=52 lane-cnt=4 property=rx data=0x1.0.3.2
-phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=rx data=0x2.0.1.3
-phy set lane-swap unit=0 portlist=54 lane-cnt=4 property=rx data=0x1.0.3.2
-phy set lane-swap unit=0 portlist=55 lane-cnt=4 property=rx data=0x1.0.3.2
+phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=rx data=0x1.0.3.2
phy set lane-swap unit=0 portlist=129 lane-cnt=1 property=rx data=0x1
phy set lane-swap unit=0 portlist=130 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=0 lane-cnt=1 property=tx data=0x0
@@ -230,8 +224,6 @@ phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=51 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=52 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=53 lane-cnt=4 property=tx data=0x0.0.0.0
-phy set polarity-rev unit=0 portlist=54 lane-cnt=4 property=tx data=0x0.0.0.0
-phy set polarity-rev unit=0 portlist=55 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=129 lane-cnt=1 property=tx data=0x0
phy set polarity-rev unit=0 portlist=130 lane-cnt=1 property=tx data=0x0
phy set polarity-rev unit=0 portlist=0 lane-cnt=1 property=rx data=0x0
@@ -284,12 +276,10 @@ phy set polarity-rev unit=0 portlist=46 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=47 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=48 lane-cnt=4 property=rx data=0x0.1.1.0
phy set polarity-rev unit=0 portlist=49 lane-cnt=4 property=rx data=0x0.0.0.0
-phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=rx data=0x1.1.1.1
+phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=rx data=0x1.1.1.0
phy set polarity-rev unit=0 portlist=51 lane-cnt=4 property=rx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=52 lane-cnt=4 property=rx data=0x1.1.1.0
phy set polarity-rev unit=0 portlist=53 lane-cnt=4 property=rx data=0x0.0.0.0
-phy set polarity-rev unit=0 portlist=54 lane-cnt=4 property=rx data=0x1.1.1.0
-phy set polarity-rev unit=0 portlist=55 lane-cnt=4 property=rx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=129 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=130 lane-cnt=1 property=rx data=0x0
phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c2 data=0x2
@@ -508,14 +498,6 @@ phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c2 data=0x2.2.2.2
phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=cn1 data=0x0.0.0.0
phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b
phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c1 data=0x6.6.6.6
-phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=c2 data=0x2.2.2.2
-phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=cn1 data=0x0.0.0.0
-phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b
-phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=c1 data=0x6.6.6.6
-phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=c2 data=0x2.2.2.2
-phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=cn1 data=0x0.0.0.0
-phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b
-phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=c1 data=0x6.6.6.6
phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c2 data=0x1
phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=cn1 data=0x1
phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c0 data=0x2
@@ -524,62 +506,60 @@ phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=c2 data=0x1
phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=cn1 data=0x0
phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=c0 data=0x2
phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=c1 data=0x3
-port set property unit=0 portlist=0 speed=25g
-port set property unit=0 portlist=1 speed=25g
-port set property unit=0 portlist=2 speed=25g
-port set property unit=0 portlist=3 speed=25g
-port set property unit=0 portlist=4 speed=25g
-port set property unit=0 portlist=5 speed=25g
-port set property unit=0 portlist=6 speed=25g
-port set property unit=0 portlist=7 speed=25g
-port set property unit=0 portlist=8 speed=25g
-port set property unit=0 portlist=9 speed=25g
-port set property unit=0 portlist=10 speed=25g
-port set property unit=0 portlist=11 speed=25g
-port set property unit=0 portlist=12 speed=25g
-port set property unit=0 portlist=13 speed=25g
-port set property unit=0 portlist=14 speed=25g
-port set property unit=0 portlist=15 speed=25g
-port set property unit=0 portlist=16 speed=25g
-port set property unit=0 portlist=17 speed=25g
-port set property unit=0 portlist=18 speed=25g
-port set property unit=0 portlist=19 speed=25g
-port set property unit=0 portlist=20 speed=25g
-port set property unit=0 portlist=21 speed=25g
-port set property unit=0 portlist=22 speed=25g
-port set property unit=0 portlist=23 speed=25g
-port set property unit=0 portlist=24 speed=25g
-port set property unit=0 portlist=25 speed=25g
-port set property unit=0 portlist=26 speed=25g
-port set property unit=0 portlist=27 speed=25g
-port set property unit=0 portlist=28 speed=25g
-port set property unit=0 portlist=29 speed=25g
-port set property unit=0 portlist=30 speed=25g
-port set property unit=0 portlist=31 speed=25g
-port set property unit=0 portlist=32 speed=25g
-port set property unit=0 portlist=33 speed=25g
-port set property unit=0 portlist=34 speed=25g
-port set property unit=0 portlist=35 speed=25g
-port set property unit=0 portlist=36 speed=25g
-port set property unit=0 portlist=37 speed=25g
-port set property unit=0 portlist=38 speed=25g
-port set property unit=0 portlist=39 speed=25g
-port set property unit=0 portlist=40 speed=25g
-port set property unit=0 portlist=41 speed=25g
-port set property unit=0 portlist=42 speed=25g
-port set property unit=0 portlist=43 speed=25g
-port set property unit=0 portlist=44 speed=25g
-port set property unit=0 portlist=45 speed=25g
-port set property unit=0 portlist=46 speed=25g
-port set property unit=0 portlist=47 speed=25g
+port set property unit=0 portlist=0 speed=10g
+port set property unit=0 portlist=1 speed=10g
+port set property unit=0 portlist=2 speed=10g
+port set property unit=0 portlist=3 speed=10g
+port set property unit=0 portlist=4 speed=10g
+port set property unit=0 portlist=5 speed=10g
+port set property unit=0 portlist=6 speed=10g
+port set property unit=0 portlist=7 speed=10g
+port set property unit=0 portlist=8 speed=10g
+port set property unit=0 portlist=9 speed=10g
+port set property unit=0 portlist=10 speed=10g
+port set property unit=0 portlist=11 speed=10g
+port set property unit=0 portlist=12 speed=10g
+port set property unit=0 portlist=13 speed=10g
+port set property unit=0 portlist=14 speed=10g
+port set property unit=0 portlist=15 speed=10g
+port set property unit=0 portlist=16 speed=10g
+port set property unit=0 portlist=17 speed=10g
+port set property unit=0 portlist=18 speed=10g
+port set property unit=0 portlist=19 speed=10g
+port set property unit=0 portlist=20 speed=10g
+port set property unit=0 portlist=21 speed=10g
+port set property unit=0 portlist=22 speed=10g
+port set property unit=0 portlist=23 speed=10g
+port set property unit=0 portlist=24 speed=10g
+port set property unit=0 portlist=25 speed=10g
+port set property unit=0 portlist=26 speed=10g
+port set property unit=0 portlist=27 speed=10g
+port set property unit=0 portlist=28 speed=10g
+port set property unit=0 portlist=29 speed=10g
+port set property unit=0 portlist=30 speed=10g
+port set property unit=0 portlist=31 speed=10g
+port set property unit=0 portlist=32 speed=10g
+port set property unit=0 portlist=33 speed=10g
+port set property unit=0 portlist=34 speed=10g
+port set property unit=0 portlist=35 speed=10g
+port set property unit=0 portlist=36 speed=10g
+port set property unit=0 portlist=37 speed=10g
+port set property unit=0 portlist=38 speed=10g
+port set property unit=0 portlist=39 speed=10g
+port set property unit=0 portlist=40 speed=10g
+port set property unit=0 portlist=41 speed=10g
+port set property unit=0 portlist=42 speed=10g
+port set property unit=0 portlist=43 speed=10g
+port set property unit=0 portlist=44 speed=10g
+port set property unit=0 portlist=45 speed=10g
+port set property unit=0 portlist=46 speed=10g
+port set property unit=0 portlist=47 speed=10g
port set property unit=0 portlist=48 speed=100g
port set property unit=0 portlist=49 speed=100g
port set property unit=0 portlist=50 speed=100g
port set property unit=0 portlist=51 speed=100g
port set property unit=0 portlist=52 speed=100g
port set property unit=0 portlist=53 speed=100g
-port set property unit=0 portlist=54 speed=100g
-port set property unit=0 portlist=55 speed=100g
port set property unit=0 portlist=129 speed=10g
port set property unit=0 portlist=130 speed=1g
port set property unit=0 portlist=0 medium-type=sr
@@ -636,8 +616,6 @@ port set property unit=0 portlist=50 medium-type=sr4
port set property unit=0 portlist=51 medium-type=sr4
port set property unit=0 portlist=52 medium-type=sr4
port set property unit=0 portlist=53 medium-type=sr4
-port set property unit=0 portlist=54 medium-type=sr4
-port set property unit=0 portlist=55 medium-type=sr4
port set property unit=0 portlist=129 medium-type=kr
port set property unit=0 portlist=130 medium-type=x
port advertise unit=0 portlist=129 speed-10g-kr
@@ -696,7 +674,5 @@ port set property unit=0 portlist=50 admin=enable
port set property unit=0 portlist=51 admin=enable
port set property unit=0 portlist=52 admin=enable
port set property unit=0 portlist=53 admin=enable
-port set property unit=0 portlist=54 admin=enable
-port set property unit=0 portlist=55 admin=enable
-port set property unit=0 portlist=129 admin=enable
-port set property unit=0 portlist=130 admin=enable
+port set property unit=0 portlist=129 admin=disable
+port set property unit=0 portlist=130 admin=disable
diff --git a/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/qos.json.j2 b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/qos.json.j2
new file mode 100644
index 000000000000..3e548325ea30
--- /dev/null
+++ b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/qos.json.j2
@@ -0,0 +1 @@
+{%- include 'qos_config.j2' %}
diff --git a/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/sai.profile b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/sai.profile
new file mode 100644
index 000000000000..e7b5f90ac88a
--- /dev/null
+++ b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/sai.profile
@@ -0,0 +1,3 @@
+SAI_INIT_LED_CONFIG_FILE=/usr/share/sonic/hwsku/led.bin
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/proc_init.nps
+SAI_DSH_CONFIG_FILE=/usr/share/sonic/hwsku/port_config.nps
diff --git a/device/cig/x86_64-cig_cs5435_54p-r0/default_sku b/device/cig/x86_64-cig_cs5435_54p-r0/default_sku
new file mode 100644
index 000000000000..66b35b61e09b
--- /dev/null
+++ b/device/cig/x86_64-cig_cs5435_54p-r0/default_sku
@@ -0,0 +1 @@
+Cig-CS5435-54P t1
diff --git a/device/cig/x86_64-cig_cs5435_54p-r0/installer.conf b/device/cig/x86_64-cig_cs5435_54p-r0/installer.conf
new file mode 100644
index 000000000000..ea6b4f6ebe31
--- /dev/null
+++ b/device/cig/x86_64-cig_cs5435_54p-r0/installer.conf
@@ -0,0 +1,4 @@
+CONSOLE_PORT=0x3f8
+CONSOLE_DEV=0
+CONSOLE_SPEED=115200
+ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pci=noaer"
diff --git a/device/cig/x86_64-cig_cs5435_54p-r0/plugins/eeprom.py b/device/cig/x86_64-cig_cs5435_54p-r0/plugins/eeprom.py
new file mode 100755
index 000000000000..5019b9c40a9a
--- /dev/null
+++ b/device/cig/x86_64-cig_cs5435_54p-r0/plugins/eeprom.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+try:
+ import exceptions
+ import binascii
+ import time
+ import optparse
+ import warnings
+ import os
+ import sys
+ from sonic_eeprom import eeprom_base
+ from sonic_eeprom import eeprom_tlvinfo
+ import subprocess
+except ImportError, e:
+ raise ImportError (str(e) + "- required module not found")
+
+class board(eeprom_tlvinfo.TlvInfoDecoder):
+ _TLV_INFO_MAX_LEN = 256
+ def __init__(self, name, path, cpld_root, ro):
+ self.eeprom_path = "/sys/bus/i2c/devices/7-0057/eeprom"
+ super(board, self).__init__(self.eeprom_path, 0, '', True)
diff --git a/device/cig/x86_64-cig_cs5435_54p-r0/plugins/psuutil.py b/device/cig/x86_64-cig_cs5435_54p-r0/plugins/psuutil.py
new file mode 100755
index 000000000000..70d50e6c3458
--- /dev/null
+++ b/device/cig/x86_64-cig_cs5435_54p-r0/plugins/psuutil.py
@@ -0,0 +1,93 @@
+#
+# psuutil.py
+# Platform-specific PSU status interface for SONiC
+#
+
+
+import os.path
+import logging
+
+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"""
+
+ SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/5-005a",
+ "/sys/bus/i2c/devices/5-005b"]
+
+ def __init__(self):
+ PsuBase.__init__(self)
+
+
+ # Get sysfs attribute
+ def get_attr_value(self, attr_path):
+
+ retval = 'ERR'
+ if (not os.path.isfile(attr_path)):
+ return retval
+
+ try:
+ with open(attr_path, 'r') as fd:
+ retval = fd.read()
+ except Exception as error:
+ logging.error("Unable to open %s file !", attr_path)
+
+ retval = retval.rstrip('\r\n')
+ return retval
+
+ 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
+ """
+ MAX_PSUS = 2
+ return MAX_PSUS
+
+ def get_psu_status(self, index):
+ """
+ Retrieves the oprational status of power supply unit (PSU) defined
+ by index
+ :param index: An integer, index of the PSU of which to query status
+ :return: Boolean, True if PSU is operating properly, False if PSU is\
+ faulty
+ """
+ status = 0
+ attr_file = 'psu_power_good'
+ attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file
+
+ attr_value = self.get_attr_value(attr_path)
+
+ if (attr_value != 'ERR'):
+ attr_value = int(attr_value, 16)
+ # Check for PSU status
+ if (attr_value == 1):
+ status = 1
+
+ return status
+
+ def get_psu_presence(self, index):
+ """
+ Retrieves the presence status of power supply unit (PSU) defined
+ by index
+ :param index: An integer, index of the PSU of which to query status
+ :return: Boolean, True if PSU is plugged, False if not
+ """
+ status = 0
+ psu_absent = 0
+ attr_file ='psu_present'
+ attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file
+
+ attr_value = self.get_attr_value(attr_path)
+
+ if (attr_value != 'ERR'):
+ attr_value = int(attr_value, 16)
+ # Check for PSU presence
+ if (attr_value == 1):
+ status = 1
+
+ return status
+
diff --git a/device/cig/x86_64-cig_cs5435_54p-r0/plugins/sfputil.py b/device/cig/x86_64-cig_cs5435_54p-r0/plugins/sfputil.py
new file mode 100755
index 000000000000..2863b80c9950
--- /dev/null
+++ b/device/cig/x86_64-cig_cs5435_54p-r0/plugins/sfputil.py
@@ -0,0 +1,250 @@
+#!/usr/bin/env python
+
+try:
+ import time
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError, e:
+ raise ImportError (str(e) + "- required module not found")
+
+
+class SfpUtil(SfpUtilBase):
+ """Platform specific SfpUtill class"""
+
+ _port_start = 1
+ _port_end = 54
+ _qsfp_port_start = 49
+ _ports_in_block = 54
+
+ _port_to_eeprom_mapping = {}
+ _global_port_pres_dict = {}
+
+ _port_to_i2c_mapping = {
+ 1 : 8,
+ 2 : 9,
+ 3 : 10,
+ 4 : 11,
+ 5 : 12,
+ 6 : 13,
+ 7 : 14,
+ 8 : 15,
+ 9 : 16,
+ 10: 17,
+ 11 : 18,
+ 12 : 19,
+ 13 : 20,
+ 14 : 21,
+ 15 : 22,
+ 16 : 23,
+ 17 : 24,
+ 18 : 25,
+ 19 : 26,
+ 20 : 27,
+ 21 : 28,
+ 22 : 29,
+ 23 : 30,
+ 24 : 31,
+ 25 : 32,
+ 26 : 33,
+ 27 : 34,
+ 28 : 35,
+ 29 : 36,
+ 30 : 37,
+ 31 : 38,
+ 32 : 39,
+ 33 : 40,
+ 34 : 41,
+ 35 : 42,
+ 36 : 43,
+ 37 : 44,
+ 38 : 45,
+ 39 : 46,
+ 40 : 47,
+ 41 : 48,
+ 42 : 49,
+ 43 : 50,
+ 44 : 51,
+ 45 : 52,
+ 46 : 53,
+ 47 : 54,
+ 48 : 55,
+ 49 : 56,
+ 50 : 57,
+ 51 : 60,
+ 52 : 61,
+ 53 : 62,
+ 54 : 63,
+ }
+
+ _qsfp_ports = range(_qsfp_port_start, _ports_in_block + 1)
+
+ def get_presence(self, port_num):
+ # Check for invalid port_num
+ if port_num < self._port_start or port_num > self._port_end:
+ return False
+
+ path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present"
+ port_ps = path.format(self._port_to_i2c_mapping[port_num])
+
+
+ try:
+ reg_file = open(port_ps)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ try:
+ reg_value = reg_file.readline().rstrip()
+ except IOError as e:
+ time.sleep(1)
+
+ try:
+ reg_value = reg_file.readline().rstrip()
+ except IOError as e:
+ print "Error:try again to read file failed: %s %s" % (str(e), port_ps)
+ reg_file.close()
+ return False
+
+ reg_file.close()
+ if reg_value == '1':
+ return True
+
+ reg_file.close()
+ if reg_value == '1':
+ return True
+
+ return False
+
+ def init_global_port_presence(self):
+ for port_num in range(self.port_start, (self.port_end + 1)):
+ self._global_port_pres_dict[port_num] = '0'
+
+
+ def __init__(self):
+ eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom'
+ for x in range(self._port_start, self._port_end + 1):
+ port_eeprom_path = eeprom_path.format(self._port_to_i2c_mapping[x])
+ self._port_to_eeprom_mapping[x] = port_eeprom_path
+
+ self.init_global_port_presence()
+ SfpUtilBase.__init__(self)
+
+ def reset(self, port_num):
+ # Check for invalid port_num
+ if port_num < self._port_start or port_num > self._port_end:
+ return False
+
+ path = "/sys/bus/i2c/devices/{0}-0050/sfp_port_reset"
+ port_ps = path.format(self._port_to_i2c_mapping[port_num])
+
+ try:
+ reg_file = open(port_ps, 'w')
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ #toggle reset
+ reg_file.seek(0)
+ reg_file.write('1')
+ time.sleep(1)
+ reg_file.seek(0)
+ reg_file.write('0')
+ reg_file.close()
+ return True
+
+ def set_low_power_mode(self, port_num, lpmode):
+ # Check for invalid port_num
+ if port_num < self._qsfp_port_start or port_num > self._port_end:
+ return False
+
+ pre_value = self.get_presence(port_num)
+ if pre_value == False:
+ return False
+
+ path = "/sys/bus/i2c/devices/{0}-0050/sfp_lpmode"
+ port_ps = path.format(self._port_to_i2c_mapping[port_num])
+
+ try:
+ reg_file = open(port_ps,'w')
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_file.seek(0)
+
+ if lpmode == 1:
+ reg_file.write('1')
+ elif lpmode == 0:
+ reg_file.write('0')
+ reg_file.close()
+
+ return True
+
+
+ def get_low_power_mode(self, port_num):
+ # Check for invalid port_num
+
+ if port_num < self._qsfp_port_start or port_num > self._port_end:
+ return False
+
+ pre_value = self.get_presence(port_num)
+ if pre_value == False:
+ return False
+
+ path = "/sys/bus/i2c/devices/{0}-0050/sfp_lpmode"
+ port_ps = path.format(self._port_to_i2c_mapping[port_num])
+
+ try:
+ reg_file = open(port_ps)
+ except IOError as e:
+ print "Error: unable to open file:%s %s" % (str(e), port_ps)
+ return False
+
+ try:
+ reg_value = reg_file.readline().rstrip()
+ except IOError as e:
+ print "Error: unable to open file:%s %s" % (str(e), port_ps)
+ reg_file.close()
+ return False
+
+ reg_file.close()
+
+ if reg_value == '1':
+ return True
+
+ return False
+
+ def get_transceiver_change_event(self):
+ port_dict = {}
+ while True:
+ for port_num in range(self.port_start, (self.port_end + 1)):
+ presence = self.get_presence(port_num)
+
+ if(presence and self._global_port_pres_dict[port_num] == '0'):
+ self._global_port_pres_dict[port_num] = '1'
+ port_dict[port_num] = '1'
+ elif(not presence and
+ self._global_port_pres_dict[port_num] == '1'):
+ self._global_port_pres_dict[port_num] = '0'
+ port_dict[port_num] = '0'
+
+ if(len(port_dict) > 0):
+ return True, port_dict
+
+ time.sleep(0.5)
+
+
+ @property
+ def port_start(self):
+ return self._port_start
+
+ @property
+ def port_end(self):
+ return self._port_end
+
+ @property
+ def qsfp_ports(self):
+ return self._qsfp_ports
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
diff --git a/device/cig/x86_64-cig_cs5435_54p-r0/sensors.conf b/device/cig/x86_64-cig_cs5435_54p-r0/sensors.conf
new file mode 100644
index 000000000000..f0964c87dae7
--- /dev/null
+++ b/device/cig/x86_64-cig_cs5435_54p-r0/sensors.conf
@@ -0,0 +1,13 @@
+# libsensors configuration file
+
+chip "cs5435_54p_fan-*"
+ label fan1 "front fan 1"
+ label fan2 "front fan 2"
+ label fan3 "front fan 3"
+ label fan4 "front fan 4"
+ label fan5 "front fan 5"
+ label fan6 "rear fan 1"
+ label fan7 "rear fan 2"
+ label fan8 "rear fan 3"
+ label fan9 "rear fan 4"
+ label fan10 "rear fan 5"
diff --git a/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/buffers.json.j2 b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/buffers.json.j2
new file mode 100644
index 000000000000..2c391214fa65
--- /dev/null
+++ b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/buffers.json.j2
@@ -0,0 +1,111 @@
+{# Default values which will be used if no actual configura available #}
+{% set default_cable = '40m' %}
+{% set default_speed = '10G' %}
+{% set default_ports_num = 54 -%}
+
+{# Port configuration to cable length look-up table #}
+{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #}
+{# Roles described in the minigraph #}
+{% set ports2cable = {
+ 'torrouter_server' : '5m',
+ 'leafrouter_torrouter' : '40m',
+ 'spinerouter_leafrouter' : '300m'
+ }
+%}
+
+{%- macro cable_length(port_name) -%}
+ {%- set cable_len = [] -%}
+ {%- for local_port in DEVICE_NEIGHBOR -%}
+ {%- if local_port == port_name -%}
+ {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
+ {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
+ {%- set neighbor_role = neighbor.type -%}
+ {%- set roles1 = switch_role + '_' + neighbor_role %}
+ {%- set roles2 = neighbor_role + '_' + switch_role -%}
+ {%- set roles1 = roles1 | lower -%}
+ {%- set roles2 = roles2 | lower -%}
+ {%- if roles1 in ports2cable -%}
+ {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%}
+ {%- elif roles2 in ports2cable -%}
+ {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%}
+ {%- endif -%}
+ {%- endif -%}
+ {%- endif -%}
+ {%- endfor -%}
+ {%- if cable_len -%}
+ {{ cable_len.0 }}
+ {%- else -%}
+ {{ default_cable }}
+ {%- endif -%}
+{% endmacro %}
+
+{%- if DEVICE_METADATA is defined %}
+{%- set switch_role = DEVICE_METADATA['localhost']['type'] %}
+{%- endif -%}
+
+{# Generate list of ports if not defined #}
+{% if PORT is not defined %}
+ {% set PORT = [] %}
+ {% for port_idx in range(0,default_ports_num) %}
+ {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %}
+ {% endfor %}
+{% endif -%}
+
+{% set port_names_list = [] %}
+{% for port in PORT %}
+ {%- if port_names_list.append(port) %}{% endif %}
+{% endfor %}
+{% set port_names = port_names_list | join(',') -%}
+
+{
+ "CABLE_LENGTH": {
+ "AZURE": {
+ {% for port in PORT %}
+ {% set cable = cable_length(port) -%}
+ "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %}
+
+ {% endfor %}
+ }
+ },
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "20971328",
+ "type": "ingress",
+ "mode": "static"
+ },
+ "ingress_lossy_pool": {
+ "size": "20971328",
+ "type": "ingress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "20971328",
+ "type": "egress",
+ "mode": "static"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossless_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "xon":"78400",
+ "xoff":"132160",
+ "size":"3584",
+ "static_th":"82880"
+ },
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossy_pool]",
+ "size":"3584",
+ "dynamic_th":"-1"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"3584",
+ "dynamic_th":"-4"
+ }
+ },
+ "BUFFER_PG": {
+ },
+ "BUFFER_QUEUE": {
+ }
+}
+
\ No newline at end of file
diff --git a/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/led.bin b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/led.bin
new file mode 100644
index 000000000000..201662a1c605
Binary files /dev/null and b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/led.bin differ
diff --git a/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/pg_profile_lookup.ini b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/pg_profile_lookup.ini
new file mode 100644
index 000000000000..d98b0eca6d19
--- /dev/null
+++ b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/pg_profile_lookup.ini
@@ -0,0 +1,17 @@
+# PG lossless profiles.
+# speed cable size xon xoff threshold
+ 10000 5m 3584 32256 59136 36736
+ 25000 5m 3584 41216 68096 45696
+ 40000 5m 3584 47488 74368 51968
+ 50000 5m 3584 52864 79744 57344
+ 100000 5m 3584 78400 132160 82880
+ 10000 40m 3584 32256 59136 36736
+ 25000 40m 3584 41216 68096 45696
+ 40000 40m 3584 47488 74368 51968
+ 50000 40m 3584 52864 79744 57344
+ 100000 40m 3584 78400 132160 82880
+ 10000 300m 3584 32256 65856 36736
+ 25000 300m 3584 41216 84672 45696
+ 40000 300m 3584 47488 101024 51968
+ 50000 300m 3584 52864 113120 57344
+ 100000 300m 3584 78400 198688 82880
\ No newline at end of file
diff --git a/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/port_config.ini b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/port_config.ini
new file mode 100644
index 000000000000..165b5204c2f8
--- /dev/null
+++ b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/port_config.ini
@@ -0,0 +1,55 @@
+# name lanes alias index speed
+Ethernet0 8 Ethernet1/1 1 25000
+Ethernet1 9 Ethernet2/1 2 25000
+Ethernet2 10 Ethernet3/1 3 25000
+Ethernet3 11 Ethernet4/1 4 25000
+Ethernet4 12 Ethernet5/1 5 25000
+Ethernet5 13 Ethernet6/1 6 25000
+Ethernet6 14 Ethernet7/1 7 25000
+Ethernet7 15 Ethernet8/1 8 25000
+Ethernet8 16 Ethernet9/1 9 25000
+Ethernet9 17 Ethernet10/1 10 25000
+Ethernet10 18 Ethernet11/1 11 25000
+Ethernet11 19 Ethernet12/1 12 25000
+Ethernet12 20 Ethernet13/1 13 25000
+Ethernet13 21 Ethernet14/1 14 25000
+Ethernet14 22 Ethernet15/1 15 25000
+Ethernet15 23 Ethernet16/1 16 25000
+Ethernet16 32 Ethernet17/1 17 25000
+Ethernet17 33 Ethernet18/1 18 25000
+Ethernet18 34 Ethernet19/1 19 25000
+Ethernet19 35 Ethernet20/1 20 25000
+Ethernet20 40 Ethernet21/1 21 25000
+Ethernet21 41 Ethernet22/1 22 25000
+Ethernet22 42 Ethernet23/1 23 25000
+Ethernet23 43 Ethernet24/1 24 25000
+Ethernet24 48 Ethernet25/1 25 25000
+Ethernet25 49 Ethernet26/1 26 25000
+Ethernet26 50 Ethernet27/1 27 25000
+Ethernet27 51 Ethernet28/1 28 25000
+Ethernet28 56 Ethernet29/1 29 25000
+Ethernet29 57 Ethernet30/1 30 25000
+Ethernet30 58 Ethernet31/1 31 25000
+Ethernet31 59 Ethernet32/1 32 25000
+Ethernet32 64 Ethernet33/1 33 25000
+Ethernet33 65 Ethernet34/1 34 25000
+Ethernet34 66 Ethernet35/1 35 25000
+Ethernet35 67 Ethernet36/1 36 25000
+Ethernet36 68 Ethernet37/1 37 25000
+Ethernet37 69 Ethernet38/1 38 25000
+Ethernet38 70 Ethernet39/1 39 25000
+Ethernet39 71 Ethernet40/1 40 25000
+Ethernet40 72 Ethernet41/1 41 25000
+Ethernet41 73 Ethernet42/1 42 25000
+Ethernet42 74 Ethernet43/1 43 25000
+Ethernet43 75 Ethernet44/1 44 25000
+Ethernet44 76 Ethernet45/1 45 25000
+Ethernet45 77 Ethernet46/1 46 25000
+Ethernet46 78 Ethernet47/1 47 25000
+Ethernet47 79 Ethernet48/1 48 25000
+Ethernet48 84,85,86,87 Ethernet49/1 49 100000
+Ethernet49 80,81,82,83 Ethernet50/1 50 100000
+Ethernet50 108,109,110,111 Ethernet51/1 51 100000
+Ethernet51 104,105,106,107 Ethernet52/1 52 100000
+Ethernet52 116,117,118,119 Ethernet53/1 53 100000
+Ethernet53 112,113,114,115 Ethernet54/1 54 100000
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.nps.AOC.R0B b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/port_config.nps
old mode 100755
new mode 100644
similarity index 92%
rename from device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.nps.AOC.R0B
rename to device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/port_config.nps
index 857e5f1ede5f..aca222f5962d
--- a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.nps.AOC.R0B
+++ b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/port_config.nps
@@ -1,24 +1,24 @@
init start stage unit=0 low-level
-init set port-map unit=0 port=0 eth-macro=2 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=1 eth-macro=2 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=2 eth-macro=2 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=3 eth-macro=2 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=4 eth-macro=3 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=5 eth-macro=3 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=6 eth-macro=3 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=7 eth-macro=3 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=8 eth-macro=4 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=9 eth-macro=4 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=10 eth-macro=4 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=11 eth-macro=4 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=12 eth-macro=5 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=13 eth-macro=5 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=14 eth-macro=5 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=15 eth-macro=5 lane=3 max-speed=25g active=true
-init set port-map unit=0 port=16 eth-macro=8 lane=0 max-speed=25g active=true
-init set port-map unit=0 port=17 eth-macro=8 lane=1 max-speed=25g active=true
-init set port-map unit=0 port=18 eth-macro=8 lane=2 max-speed=25g active=true
-init set port-map unit=0 port=19 eth-macro=8 lane=3 max-speed=25g active=true
+init set port-map unit=0 port=0 eth-macro=2 lane=0 max-speed=25g active=true
+init set port-map unit=0 port=1 eth-macro=2 lane=1 max-speed=25g active=true
+init set port-map unit=0 port=2 eth-macro=2 lane=2 max-speed=25g active=true
+init set port-map unit=0 port=3 eth-macro=2 lane=3 max-speed=25g active=true
+init set port-map unit=0 port=4 eth-macro=3 lane=0 max-speed=25g active=true
+init set port-map unit=0 port=5 eth-macro=3 lane=1 max-speed=25g active=true
+init set port-map unit=0 port=6 eth-macro=3 lane=2 max-speed=25g active=true
+init set port-map unit=0 port=7 eth-macro=3 lane=3 max-speed=25g active=true
+init set port-map unit=0 port=8 eth-macro=4 lane=0 max-speed=25g active=true
+init set port-map unit=0 port=9 eth-macro=4 lane=1 max-speed=25g active=true
+init set port-map unit=0 port=10 eth-macro=4 lane=2 max-speed=25g active=true
+init set port-map unit=0 port=11 eth-macro=4 lane=3 max-speed=25g active=true
+init set port-map unit=0 port=12 eth-macro=5 lane=0 max-speed=25g active=true
+init set port-map unit=0 port=13 eth-macro=5 lane=1 max-speed=25g active=true
+init set port-map unit=0 port=14 eth-macro=5 lane=2 max-speed=25g active=true
+init set port-map unit=0 port=15 eth-macro=5 lane=3 max-speed=25g active=true
+init set port-map unit=0 port=16 eth-macro=8 lane=0 max-speed=25g active=true
+init set port-map unit=0 port=17 eth-macro=8 lane=1 max-speed=25g active=true
+init set port-map unit=0 port=18 eth-macro=8 lane=2 max-speed=25g active=true
+init set port-map unit=0 port=19 eth-macro=8 lane=3 max-speed=25g active=true
init set port-map unit=0 port=20 eth-macro=10 lane=0 max-speed=25g active=true
init set port-map unit=0 port=21 eth-macro=10 lane=1 max-speed=25g active=true
init set port-map unit=0 port=22 eth-macro=10 lane=2 max-speed=25g active=true
@@ -49,12 +49,10 @@ init set port-map unit=0 port=46 eth-macro=19 lane=2 max-speed=25g active=true
init set port-map unit=0 port=47 eth-macro=19 lane=3 max-speed=25g active=true
init set port-map unit=0 port=48 eth-macro=21 lane=0 max-speed=100g active=true
init set port-map unit=0 port=49 eth-macro=20 lane=0 max-speed=100g active=true
-init set port-map unit=0 port=50 eth-macro=23 lane=0 max-speed=100g active=true
-init set port-map unit=0 port=51 eth-macro=22 lane=0 max-speed=100g active=true
-init set port-map unit=0 port=52 eth-macro=27 lane=0 max-speed=100g active=true
-init set port-map unit=0 port=53 eth-macro=26 lane=0 max-speed=100g active=true
-init set port-map unit=0 port=54 eth-macro=29 lane=0 max-speed=100g active=true
-init set port-map unit=0 port=55 eth-macro=28 lane=0 max-speed=100g active=true
+init set port-map unit=0 port=50 eth-macro=27 lane=0 max-speed=100g active=true
+init set port-map unit=0 port=51 eth-macro=26 lane=0 max-speed=100g active=true
+init set port-map unit=0 port=52 eth-macro=29 lane=0 max-speed=100g active=true
+init set port-map unit=0 port=53 eth-macro=28 lane=0 max-speed=100g active=true
init set port-map unit=0 port=129 eth-macro=0 lane=1 max-speed=10g active=true guarantee=true cpi=true
init set port-map unit=0 port=130 eth-macro=0 lane=0 max-speed=10g active=true guarantee=true cpi=true init-done=true
init start stage unit=0 task-rsrc
@@ -110,12 +108,10 @@ phy set lane-swap unit=0 portlist=46 lane-cnt=1 property=tx data=0x2
phy set lane-swap unit=0 portlist=47 lane-cnt=1 property=tx data=0x3
phy set lane-swap unit=0 portlist=48 lane-cnt=4 property=tx data=0x3.0.1.2
phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=tx data=0x3.2.1.0
-phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=tx data=0x0.1.2.3
-phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=tx data=0x3.2.0.1
+phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=tx data=0x3.2.1.0
+phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=52 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=tx data=0x3.2.1.0
-phy set lane-swap unit=0 portlist=54 lane-cnt=4 property=tx data=0x3.2.1.0
-phy set lane-swap unit=0 portlist=55 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=129 lane-cnt=1 property=tx data=0x1
phy set lane-swap unit=0 portlist=130 lane-cnt=1 property=tx data=0x0
phy set lane-swap unit=0 portlist=0 lane-cnt=1 property=rx data=0x0
@@ -168,12 +164,10 @@ phy set lane-swap unit=0 portlist=46 lane-cnt=1 property=rx data=0x0
phy set lane-swap unit=0 portlist=47 lane-cnt=1 property=rx data=0x3
phy set lane-swap unit=0 portlist=48 lane-cnt=4 property=rx data=0x3.1.0.2
phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=rx data=0x3.2.1.0
-phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=rx data=0x3.0.1.2
-phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=rx data=0x3.2.1.0
+phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=rx data=0x1.0.3.2
+phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=rx data=0x2.0.1.3
phy set lane-swap unit=0 portlist=52 lane-cnt=4 property=rx data=0x1.0.3.2
-phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=rx data=0x2.0.1.3
-phy set lane-swap unit=0 portlist=54 lane-cnt=4 property=rx data=0x1.0.3.2
-phy set lane-swap unit=0 portlist=55 lane-cnt=4 property=rx data=0x1.0.3.2
+phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=rx data=0x1.0.3.2
phy set lane-swap unit=0 portlist=129 lane-cnt=1 property=rx data=0x1
phy set lane-swap unit=0 portlist=130 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=0 lane-cnt=1 property=tx data=0x0
@@ -230,8 +224,6 @@ phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=51 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=52 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=53 lane-cnt=4 property=tx data=0x0.0.0.0
-phy set polarity-rev unit=0 portlist=54 lane-cnt=4 property=tx data=0x0.0.0.0
-phy set polarity-rev unit=0 portlist=55 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=129 lane-cnt=1 property=tx data=0x0
phy set polarity-rev unit=0 portlist=130 lane-cnt=1 property=tx data=0x0
phy set polarity-rev unit=0 portlist=0 lane-cnt=1 property=rx data=0x0
@@ -284,12 +276,10 @@ phy set polarity-rev unit=0 portlist=46 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=47 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=48 lane-cnt=4 property=rx data=0x0.1.1.0
phy set polarity-rev unit=0 portlist=49 lane-cnt=4 property=rx data=0x0.0.0.0
-phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=rx data=0x1.1.1.1
+phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=rx data=0x1.1.1.0
phy set polarity-rev unit=0 portlist=51 lane-cnt=4 property=rx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=52 lane-cnt=4 property=rx data=0x1.1.1.0
phy set polarity-rev unit=0 portlist=53 lane-cnt=4 property=rx data=0x0.0.0.0
-phy set polarity-rev unit=0 portlist=54 lane-cnt=4 property=rx data=0x1.1.1.0
-phy set polarity-rev unit=0 portlist=55 lane-cnt=4 property=rx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=129 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=130 lane-cnt=1 property=rx data=0x0
phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c2 data=0x2
@@ -508,14 +498,6 @@ phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c2 data=0x2.2.2.2
phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=cn1 data=0x0.0.0.0
phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b
phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c1 data=0x6.6.6.6
-phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=c2 data=0x2.2.2.2
-phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=cn1 data=0x0.0.0.0
-phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b
-phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=c1 data=0x6.6.6.6
-phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=c2 data=0x2.2.2.2
-phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=cn1 data=0x0.0.0.0
-phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b
-phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=c1 data=0x6.6.6.6
phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c2 data=0x1
phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=cn1 data=0x1
phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c0 data=0x2
@@ -578,8 +560,6 @@ port set property unit=0 portlist=50 speed=100g
port set property unit=0 portlist=51 speed=100g
port set property unit=0 portlist=52 speed=100g
port set property unit=0 portlist=53 speed=100g
-port set property unit=0 portlist=54 speed=100g
-port set property unit=0 portlist=55 speed=100g
port set property unit=0 portlist=129 speed=10g
port set property unit=0 portlist=130 speed=1g
port set property unit=0 portlist=0 medium-type=sr
@@ -636,8 +616,6 @@ port set property unit=0 portlist=50 medium-type=sr4
port set property unit=0 portlist=51 medium-type=sr4
port set property unit=0 portlist=52 medium-type=sr4
port set property unit=0 portlist=53 medium-type=sr4
-port set property unit=0 portlist=54 medium-type=sr4
-port set property unit=0 portlist=55 medium-type=sr4
port set property unit=0 portlist=129 medium-type=kr
port set property unit=0 portlist=130 medium-type=x
port advertise unit=0 portlist=129 speed-10g-kr
@@ -696,7 +674,5 @@ port set property unit=0 portlist=50 admin=enable
port set property unit=0 portlist=51 admin=enable
port set property unit=0 portlist=52 admin=enable
port set property unit=0 portlist=53 admin=enable
-port set property unit=0 portlist=54 admin=enable
-port set property unit=0 portlist=55 admin=enable
-port set property unit=0 portlist=129 admin=enable
-port set property unit=0 portlist=130 admin=enable
+port set property unit=0 portlist=129 admin=disable
+port set property unit=0 portlist=130 admin=disable
diff --git a/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/qos.json.j2 b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/qos.json.j2
new file mode 100644
index 000000000000..3e548325ea30
--- /dev/null
+++ b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/qos.json.j2
@@ -0,0 +1 @@
+{%- include 'qos_config.j2' %}
diff --git a/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/sai.profile b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/sai.profile
new file mode 100644
index 000000000000..e7b5f90ac88a
--- /dev/null
+++ b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/sai.profile
@@ -0,0 +1,3 @@
+SAI_INIT_LED_CONFIG_FILE=/usr/share/sonic/hwsku/led.bin
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/proc_init.nps
+SAI_DSH_CONFIG_FILE=/usr/share/sonic/hwsku/port_config.nps
diff --git a/device/cig/x86_64-cig_cs6436_54p-r0/default_sku b/device/cig/x86_64-cig_cs6436_54p-r0/default_sku
new file mode 100644
index 000000000000..24afbb73b770
--- /dev/null
+++ b/device/cig/x86_64-cig_cs6436_54p-r0/default_sku
@@ -0,0 +1 @@
+Cig-CS6436-54P t1
diff --git a/device/cig/x86_64-cig_cs6436_54p-r0/installer.conf b/device/cig/x86_64-cig_cs6436_54p-r0/installer.conf
new file mode 100644
index 000000000000..ea6b4f6ebe31
--- /dev/null
+++ b/device/cig/x86_64-cig_cs6436_54p-r0/installer.conf
@@ -0,0 +1,4 @@
+CONSOLE_PORT=0x3f8
+CONSOLE_DEV=0
+CONSOLE_SPEED=115200
+ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pci=noaer"
diff --git a/device/cig/x86_64-cig_cs6436_54p-r0/plugins/eeprom.py b/device/cig/x86_64-cig_cs6436_54p-r0/plugins/eeprom.py
new file mode 100755
index 000000000000..5019b9c40a9a
--- /dev/null
+++ b/device/cig/x86_64-cig_cs6436_54p-r0/plugins/eeprom.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+try:
+ import exceptions
+ import binascii
+ import time
+ import optparse
+ import warnings
+ import os
+ import sys
+ from sonic_eeprom import eeprom_base
+ from sonic_eeprom import eeprom_tlvinfo
+ import subprocess
+except ImportError, e:
+ raise ImportError (str(e) + "- required module not found")
+
+class board(eeprom_tlvinfo.TlvInfoDecoder):
+ _TLV_INFO_MAX_LEN = 256
+ def __init__(self, name, path, cpld_root, ro):
+ self.eeprom_path = "/sys/bus/i2c/devices/7-0057/eeprom"
+ super(board, self).__init__(self.eeprom_path, 0, '', True)
diff --git a/device/cig/x86_64-cig_cs6436_54p-r0/plugins/psuutil.py b/device/cig/x86_64-cig_cs6436_54p-r0/plugins/psuutil.py
new file mode 100755
index 000000000000..70d50e6c3458
--- /dev/null
+++ b/device/cig/x86_64-cig_cs6436_54p-r0/plugins/psuutil.py
@@ -0,0 +1,93 @@
+#
+# psuutil.py
+# Platform-specific PSU status interface for SONiC
+#
+
+
+import os.path
+import logging
+
+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"""
+
+ SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/5-005a",
+ "/sys/bus/i2c/devices/5-005b"]
+
+ def __init__(self):
+ PsuBase.__init__(self)
+
+
+ # Get sysfs attribute
+ def get_attr_value(self, attr_path):
+
+ retval = 'ERR'
+ if (not os.path.isfile(attr_path)):
+ return retval
+
+ try:
+ with open(attr_path, 'r') as fd:
+ retval = fd.read()
+ except Exception as error:
+ logging.error("Unable to open %s file !", attr_path)
+
+ retval = retval.rstrip('\r\n')
+ return retval
+
+ 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
+ """
+ MAX_PSUS = 2
+ return MAX_PSUS
+
+ def get_psu_status(self, index):
+ """
+ Retrieves the oprational status of power supply unit (PSU) defined
+ by index
+ :param index: An integer, index of the PSU of which to query status
+ :return: Boolean, True if PSU is operating properly, False if PSU is\
+ faulty
+ """
+ status = 0
+ attr_file = 'psu_power_good'
+ attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file
+
+ attr_value = self.get_attr_value(attr_path)
+
+ if (attr_value != 'ERR'):
+ attr_value = int(attr_value, 16)
+ # Check for PSU status
+ if (attr_value == 1):
+ status = 1
+
+ return status
+
+ def get_psu_presence(self, index):
+ """
+ Retrieves the presence status of power supply unit (PSU) defined
+ by index
+ :param index: An integer, index of the PSU of which to query status
+ :return: Boolean, True if PSU is plugged, False if not
+ """
+ status = 0
+ psu_absent = 0
+ attr_file ='psu_present'
+ attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file
+
+ attr_value = self.get_attr_value(attr_path)
+
+ if (attr_value != 'ERR'):
+ attr_value = int(attr_value, 16)
+ # Check for PSU presence
+ if (attr_value == 1):
+ status = 1
+
+ return status
+
diff --git a/device/cig/x86_64-cig_cs6436_54p-r0/plugins/sfputil.py b/device/cig/x86_64-cig_cs6436_54p-r0/plugins/sfputil.py
new file mode 100755
index 000000000000..2863b80c9950
--- /dev/null
+++ b/device/cig/x86_64-cig_cs6436_54p-r0/plugins/sfputil.py
@@ -0,0 +1,250 @@
+#!/usr/bin/env python
+
+try:
+ import time
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError, e:
+ raise ImportError (str(e) + "- required module not found")
+
+
+class SfpUtil(SfpUtilBase):
+ """Platform specific SfpUtill class"""
+
+ _port_start = 1
+ _port_end = 54
+ _qsfp_port_start = 49
+ _ports_in_block = 54
+
+ _port_to_eeprom_mapping = {}
+ _global_port_pres_dict = {}
+
+ _port_to_i2c_mapping = {
+ 1 : 8,
+ 2 : 9,
+ 3 : 10,
+ 4 : 11,
+ 5 : 12,
+ 6 : 13,
+ 7 : 14,
+ 8 : 15,
+ 9 : 16,
+ 10: 17,
+ 11 : 18,
+ 12 : 19,
+ 13 : 20,
+ 14 : 21,
+ 15 : 22,
+ 16 : 23,
+ 17 : 24,
+ 18 : 25,
+ 19 : 26,
+ 20 : 27,
+ 21 : 28,
+ 22 : 29,
+ 23 : 30,
+ 24 : 31,
+ 25 : 32,
+ 26 : 33,
+ 27 : 34,
+ 28 : 35,
+ 29 : 36,
+ 30 : 37,
+ 31 : 38,
+ 32 : 39,
+ 33 : 40,
+ 34 : 41,
+ 35 : 42,
+ 36 : 43,
+ 37 : 44,
+ 38 : 45,
+ 39 : 46,
+ 40 : 47,
+ 41 : 48,
+ 42 : 49,
+ 43 : 50,
+ 44 : 51,
+ 45 : 52,
+ 46 : 53,
+ 47 : 54,
+ 48 : 55,
+ 49 : 56,
+ 50 : 57,
+ 51 : 60,
+ 52 : 61,
+ 53 : 62,
+ 54 : 63,
+ }
+
+ _qsfp_ports = range(_qsfp_port_start, _ports_in_block + 1)
+
+ def get_presence(self, port_num):
+ # Check for invalid port_num
+ if port_num < self._port_start or port_num > self._port_end:
+ return False
+
+ path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present"
+ port_ps = path.format(self._port_to_i2c_mapping[port_num])
+
+
+ try:
+ reg_file = open(port_ps)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ try:
+ reg_value = reg_file.readline().rstrip()
+ except IOError as e:
+ time.sleep(1)
+
+ try:
+ reg_value = reg_file.readline().rstrip()
+ except IOError as e:
+ print "Error:try again to read file failed: %s %s" % (str(e), port_ps)
+ reg_file.close()
+ return False
+
+ reg_file.close()
+ if reg_value == '1':
+ return True
+
+ reg_file.close()
+ if reg_value == '1':
+ return True
+
+ return False
+
+ def init_global_port_presence(self):
+ for port_num in range(self.port_start, (self.port_end + 1)):
+ self._global_port_pres_dict[port_num] = '0'
+
+
+ def __init__(self):
+ eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom'
+ for x in range(self._port_start, self._port_end + 1):
+ port_eeprom_path = eeprom_path.format(self._port_to_i2c_mapping[x])
+ self._port_to_eeprom_mapping[x] = port_eeprom_path
+
+ self.init_global_port_presence()
+ SfpUtilBase.__init__(self)
+
+ def reset(self, port_num):
+ # Check for invalid port_num
+ if port_num < self._port_start or port_num > self._port_end:
+ return False
+
+ path = "/sys/bus/i2c/devices/{0}-0050/sfp_port_reset"
+ port_ps = path.format(self._port_to_i2c_mapping[port_num])
+
+ try:
+ reg_file = open(port_ps, 'w')
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ #toggle reset
+ reg_file.seek(0)
+ reg_file.write('1')
+ time.sleep(1)
+ reg_file.seek(0)
+ reg_file.write('0')
+ reg_file.close()
+ return True
+
+ def set_low_power_mode(self, port_num, lpmode):
+ # Check for invalid port_num
+ if port_num < self._qsfp_port_start or port_num > self._port_end:
+ return False
+
+ pre_value = self.get_presence(port_num)
+ if pre_value == False:
+ return False
+
+ path = "/sys/bus/i2c/devices/{0}-0050/sfp_lpmode"
+ port_ps = path.format(self._port_to_i2c_mapping[port_num])
+
+ try:
+ reg_file = open(port_ps,'w')
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_file.seek(0)
+
+ if lpmode == 1:
+ reg_file.write('1')
+ elif lpmode == 0:
+ reg_file.write('0')
+ reg_file.close()
+
+ return True
+
+
+ def get_low_power_mode(self, port_num):
+ # Check for invalid port_num
+
+ if port_num < self._qsfp_port_start or port_num > self._port_end:
+ return False
+
+ pre_value = self.get_presence(port_num)
+ if pre_value == False:
+ return False
+
+ path = "/sys/bus/i2c/devices/{0}-0050/sfp_lpmode"
+ port_ps = path.format(self._port_to_i2c_mapping[port_num])
+
+ try:
+ reg_file = open(port_ps)
+ except IOError as e:
+ print "Error: unable to open file:%s %s" % (str(e), port_ps)
+ return False
+
+ try:
+ reg_value = reg_file.readline().rstrip()
+ except IOError as e:
+ print "Error: unable to open file:%s %s" % (str(e), port_ps)
+ reg_file.close()
+ return False
+
+ reg_file.close()
+
+ if reg_value == '1':
+ return True
+
+ return False
+
+ def get_transceiver_change_event(self):
+ port_dict = {}
+ while True:
+ for port_num in range(self.port_start, (self.port_end + 1)):
+ presence = self.get_presence(port_num)
+
+ if(presence and self._global_port_pres_dict[port_num] == '0'):
+ self._global_port_pres_dict[port_num] = '1'
+ port_dict[port_num] = '1'
+ elif(not presence and
+ self._global_port_pres_dict[port_num] == '1'):
+ self._global_port_pres_dict[port_num] = '0'
+ port_dict[port_num] = '0'
+
+ if(len(port_dict) > 0):
+ return True, port_dict
+
+ time.sleep(0.5)
+
+
+ @property
+ def port_start(self):
+ return self._port_start
+
+ @property
+ def port_end(self):
+ return self._port_end
+
+ @property
+ def qsfp_ports(self):
+ return self._qsfp_ports
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
diff --git a/device/cig/x86_64-cig_cs6436_54p-r0/sensors.conf b/device/cig/x86_64-cig_cs6436_54p-r0/sensors.conf
new file mode 100644
index 000000000000..22cd3ccda958
--- /dev/null
+++ b/device/cig/x86_64-cig_cs6436_54p-r0/sensors.conf
@@ -0,0 +1,13 @@
+# libsensors configuration file
+
+chip "cs6436_54p_fan-*"
+ label fan1 "front fan 1"
+ label fan2 "front fan 2"
+ label fan3 "front fan 3"
+ label fan4 "front fan 4"
+ label fan5 "front fan 5"
+ label fan6 "rear fan 1"
+ label fan7 "rear fan 2"
+ label fan8 "rear fan 3"
+ label fan9 "rear fan 4"
+ label fan10 "rear fan 5"
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/buffers.json.j2 b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/buffers.json.j2
old mode 100755
new mode 100644
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/led.bin b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/led.bin
new file mode 100644
index 000000000000..8b3490ca3b7c
Binary files /dev/null and b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/led.bin differ
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/pg_profile_lookup.ini b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/pg_profile_lookup.ini
old mode 100755
new mode 100644
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.ini b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.ini
old mode 100755
new mode 100644
index 0a25fc0a3454..f7914a5c4ab0
--- a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.ini
+++ b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.ini
@@ -1,57 +1,57 @@
# name lanes alias index speed
-Ethernet0 8 Ethernet1/1 0 25000
-Ethernet1 9 Ethernet2/1 1 25000
-Ethernet2 10 Ethernet3/1 2 25000
-Ethernet3 11 Ethernet4/1 3 25000
-Ethernet4 12 Ethernet5/1 4 25000
-Ethernet5 13 Ethernet6/1 5 25000
-Ethernet6 14 Ethernet7/1 6 25000
-Ethernet7 15 Ethernet8/1 7 25000
-Ethernet8 16 Ethernet9/1 8 25000
-Ethernet9 17 Ethernet10/1 9 25000
-Ethernet10 18 Ethernet11/1 10 25000
-Ethernet11 19 Ethernet12/1 11 25000
-Ethernet12 20 Ethernet13/1 12 25000
-Ethernet13 21 Ethernet14/1 13 25000
-Ethernet14 22 Ethernet15/1 14 25000
-Ethernet15 23 Ethernet16/1 15 25000
-Ethernet16 32 Ethernet17/1 16 25000
-Ethernet17 33 Ethernet18/1 17 25000
-Ethernet18 34 Ethernet19/1 18 25000
-Ethernet19 35 Ethernet20/1 19 25000
-Ethernet20 40 Ethernet21/1 20 25000
-Ethernet21 41 Ethernet22/1 21 25000
-Ethernet22 42 Ethernet23/1 22 25000
-Ethernet23 43 Ethernet24/1 23 25000
-Ethernet24 48 Ethernet25/1 24 25000
-Ethernet25 49 Ethernet26/1 25 25000
-Ethernet26 50 Ethernet27/1 26 25000
-Ethernet27 51 Ethernet28/1 27 25000
-Ethernet28 56 Ethernet29/1 28 25000
-Ethernet29 57 Ethernet30/1 29 25000
-Ethernet30 58 Ethernet31/1 30 25000
-Ethernet31 59 Ethernet32/1 31 25000
-Ethernet32 64 Ethernet33/1 32 25000
-Ethernet33 65 Ethernet34/1 33 25000
-Ethernet34 66 Ethernet35/1 34 25000
-Ethernet35 67 Ethernet36/1 35 25000
-Ethernet36 68 Ethernet37/1 36 25000
-Ethernet37 69 Ethernet38/1 37 25000
-Ethernet38 70 Ethernet39/1 38 25000
-Ethernet39 71 Ethernet40/1 39 25000
-Ethernet40 72 Ethernet41/1 40 25000
-Ethernet41 73 Ethernet42/1 41 25000
-Ethernet42 74 Ethernet43/1 42 25000
-Ethernet43 75 Ethernet44/1 43 25000
-Ethernet44 76 Ethernet45/1 44 25000
-Ethernet45 77 Ethernet46/1 45 25000
-Ethernet46 78 Ethernet47/1 46 25000
-Ethernet47 79 Ethernet48/1 47 25000
-Ethernet48 84,85,86,87 Ethernet49/1 48 100000
-Ethernet49 80,81,82,83 Ethernet50/1 49 100000
-Ethernet50 92,93,94,95 Ethernet51/1 50 100000
-Ethernet51 88,89,90,91 Ethernet52/1 51 100000
-Ethernet52 108,109,110,111 Ethernet53/1 52 100000
-Ethernet53 104,105,106,107 Ethernet54/1 53 100000
-Ethernet54 116,117,118,119 Ethernet55/1 54 100000
-Ethernet55 112,113,114,115 Ethernet56/1 55 100000
+Ethernet0 8 Ethernet1/1 1 25000
+Ethernet1 9 Ethernet2/1 2 25000
+Ethernet2 10 Ethernet3/1 3 25000
+Ethernet3 11 Ethernet4/1 4 25000
+Ethernet4 12 Ethernet5/1 5 25000
+Ethernet5 13 Ethernet6/1 6 25000
+Ethernet6 14 Ethernet7/1 7 25000
+Ethernet7 15 Ethernet8/1 8 25000
+Ethernet8 16 Ethernet9/1 9 25000
+Ethernet9 17 Ethernet10/1 10 25000
+Ethernet10 18 Ethernet11/1 11 25000
+Ethernet11 19 Ethernet12/1 12 25000
+Ethernet12 20 Ethernet13/1 13 25000
+Ethernet13 21 Ethernet14/1 14 25000
+Ethernet14 22 Ethernet15/1 15 25000
+Ethernet15 23 Ethernet16/1 16 25000
+Ethernet16 32 Ethernet17/1 17 25000
+Ethernet17 33 Ethernet18/1 18 25000
+Ethernet18 34 Ethernet19/1 19 25000
+Ethernet19 35 Ethernet20/1 20 25000
+Ethernet20 40 Ethernet21/1 21 25000
+Ethernet21 41 Ethernet22/1 22 25000
+Ethernet22 42 Ethernet23/1 23 25000
+Ethernet23 43 Ethernet24/1 24 25000
+Ethernet24 48 Ethernet25/1 25 25000
+Ethernet25 49 Ethernet26/1 26 25000
+Ethernet26 50 Ethernet27/1 27 25000
+Ethernet27 51 Ethernet28/1 28 25000
+Ethernet28 56 Ethernet29/1 29 25000
+Ethernet29 57 Ethernet30/1 30 25000
+Ethernet30 58 Ethernet31/1 31 25000
+Ethernet31 59 Ethernet32/1 32 25000
+Ethernet32 64 Ethernet33/1 33 25000
+Ethernet33 65 Ethernet34/1 34 25000
+Ethernet34 66 Ethernet35/1 35 25000
+Ethernet35 67 Ethernet36/1 36 25000
+Ethernet36 68 Ethernet37/1 37 25000
+Ethernet37 69 Ethernet38/1 38 25000
+Ethernet38 70 Ethernet39/1 39 25000
+Ethernet39 71 Ethernet40/1 40 25000
+Ethernet40 72 Ethernet41/1 41 25000
+Ethernet41 73 Ethernet42/1 42 25000
+Ethernet42 74 Ethernet43/1 43 25000
+Ethernet43 75 Ethernet44/1 44 25000
+Ethernet44 76 Ethernet45/1 45 25000
+Ethernet45 77 Ethernet46/1 46 25000
+Ethernet46 78 Ethernet47/1 47 25000
+Ethernet47 79 Ethernet48/1 48 25000
+Ethernet48 84,85,86,87 Ethernet49/1 49 100000
+Ethernet49 80,81,82,83 Ethernet50/1 50 100000
+Ethernet50 92,93,94,95 Ethernet51/1 51 100000
+Ethernet51 88,89,90,91 Ethernet52/1 52 100000
+Ethernet52 108,109,110,111 Ethernet53/1 53 100000
+Ethernet53 104,105,106,107 Ethernet54/1 54 100000
+Ethernet54 116,117,118,119 Ethernet55/1 55 100000
+Ethernet55 112,113,114,115 Ethernet56/1 56 100000
\ No newline at end of file
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.nps b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.nps
old mode 100755
new mode 100644
index 857e5f1ede5f..ec5f0273b9b5
--- a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.nps
+++ b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.nps
@@ -698,5 +698,5 @@ port set property unit=0 portlist=52 admin=enable
port set property unit=0 portlist=53 admin=enable
port set property unit=0 portlist=54 admin=enable
port set property unit=0 portlist=55 admin=enable
-port set property unit=0 portlist=129 admin=enable
-port set property unit=0 portlist=130 admin=enable
+port set property unit=0 portlist=129 admin=disable
+port set property unit=0 portlist=130 admin=disable
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/led_proc_init.nps b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/proc_init.nps
old mode 100755
new mode 100644
similarity index 90%
rename from device/cig/x86_64-cig_cs6436_56p-r0/led_proc_init.nps
rename to device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/proc_init.nps
index 3ba2f35e5517..e55ceb0fda3f
--- a/device/cig/x86_64-cig_cs6436_56p-r0/led_proc_init.nps
+++ b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/proc_init.nps
@@ -1,7 +1,7 @@
#unit NPS_CFG_TYPE_XXX param0 param1 value
#---- ---------------- ------ ------ -----
0 NPS_CFG_TYPE_USE_UNIT_PORT 0 0 1
-0 NPS_CFG_TYPE_LED_CFG 0 0 7
+0 NPS_CFG_TYPE_LED_CFG 0 0 9
0 NPS_CFG_TYPE_CPI_PORT_MODE 129 0 1
0 NPS_CFG_TYPE_CPI_PORT_MODE 130 0 1
0 NPS_CFG_TYPE_USER_BUF_CTRL 0 0 1
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/qos.json.j2 b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/qos.json.j2
old mode 100755
new mode 100644
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/sai.profile b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/sai.profile
old mode 100755
new mode 100644
index 880f47910ac1..e7b5f90ac88a
--- a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/sai.profile
+++ b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/sai.profile
@@ -1,2 +1,3 @@
-SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/led_proc_init.nps
+SAI_INIT_LED_CONFIG_FILE=/usr/share/sonic/hwsku/led.bin
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/proc_init.nps
SAI_DSH_CONFIG_FILE=/usr/share/sonic/hwsku/port_config.nps
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/default_sku b/device/cig/x86_64-cig_cs6436_56p-r0/default_sku
old mode 100755
new mode 100644
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/installer.conf b/device/cig/x86_64-cig_cs6436_56p-r0/installer.conf
old mode 100755
new mode 100644
index 01b639138116..ea6b4f6ebe31
--- a/device/cig/x86_64-cig_cs6436_56p-r0/installer.conf
+++ b/device/cig/x86_64-cig_cs6436_56p-r0/installer.conf
@@ -1,4 +1,4 @@
-CONSOLE_PORT=0x3e8
-CONSOLE_DEV=2
+CONSOLE_PORT=0x3f8
+CONSOLE_DEV=0
CONSOLE_SPEED=115200
ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pci=noaer"
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/plugins/psuutil.py b/device/cig/x86_64-cig_cs6436_56p-r0/plugins/psuutil.py
index 137531c36e16..70d50e6c3458 100755
--- a/device/cig/x86_64-cig_cs6436_56p-r0/plugins/psuutil.py
+++ b/device/cig/x86_64-cig_cs6436_56p-r0/plugins/psuutil.py
@@ -5,6 +5,7 @@
import os.path
+import logging
try:
from sonic_psu.psu_base import PsuBase
@@ -33,7 +34,7 @@ def get_attr_value(self, attr_path):
with open(attr_path, 'r') as fd:
retval = fd.read()
except Exception as error:
- logging.error("Unable to open ", attr_path, " file !")
+ logging.error("Unable to open %s file !", attr_path)
retval = retval.rstrip('\r\n')
return retval
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/plugins/sfputil.py b/device/cig/x86_64-cig_cs6436_56p-r0/plugins/sfputil.py
index f5fe6c93142e..1e15c0e886f7 100755
--- a/device/cig/x86_64-cig_cs6436_56p-r0/plugins/sfputil.py
+++ b/device/cig/x86_64-cig_cs6436_56p-r0/plugins/sfputil.py
@@ -2,7 +2,7 @@
try:
import time
- from sonic_sfp.sfputilbase import SfpUtilBase
+ from sonic_sfp.sfputilbase import SfpUtilBase
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
@@ -10,80 +10,125 @@
class SfpUtil(SfpUtilBase):
"""Platform specific SfpUtill class"""
- _port_start = 0
- _port_end = 55
- _qsfp_port_start = 48
- _ports_in_block = 55
+ _port_start = 1
+ _port_end = 56
+ _qsfp_port_start = 49
+ _ports_in_block = 56
_port_to_eeprom_mapping = {}
+ _global_port_pres_dict = {}
+
_port_to_i2c_mapping = {
- 0 : 8,
- 1 : 9,
- 2 : 10,
- 3 : 11,
- 4 : 12,
- 5 : 13,
- 6 : 14,
- 7 : 15,
- 8 : 16,
- 9 : 17,
- 10 : 18,
- 11 : 19,
- 12 : 20,
- 13 : 21,
- 14 : 22,
- 15 : 23,
- 16 : 24,
- 17 : 25,
- 18 : 26,
- 19 : 27,
- 20 : 28,
- 21 : 29,
- 22 : 30,
- 23 : 31,
- 24 : 32,
- 25 : 33,
- 26 : 34,
- 27 : 35,
- 28 : 36,
- 29 : 37,
- 30 : 38,
- 31 : 39,
- 32 : 40,
- 33 : 41,
- 34 : 42,
- 35 : 43,
- 36 : 44,
- 37 : 45,
- 38 : 46,
- 39 : 47,
- 40 : 48,
- 41 : 49,
- 42 : 50,
- 43 : 51,
- 44 : 52,
- 45 : 53,
- 46 : 54,
- 47 : 55,
- 48 : 56,
- 49 : 57,
- 50 : 58,
- 51 : 59,
- 52 : 60,
- 53 : 61,
- 54 : 62,
- 55 : 63,
+ 1 : 8,
+ 2 : 9,
+ 3 : 10,
+ 4 : 11,
+ 5 : 12,
+ 6 : 13,
+ 7 : 14,
+ 8 : 15,
+ 9 : 16,
+ 10: 17,
+ 11 : 18,
+ 12 : 19,
+ 13 : 20,
+ 14 : 21,
+ 15 : 22,
+ 16 : 23,
+ 17 : 24,
+ 18 : 25,
+ 19 : 26,
+ 20 : 27,
+ 21 : 28,
+ 22 : 29,
+ 23 : 30,
+ 24 : 31,
+ 25 : 32,
+ 26 : 33,
+ 27 : 34,
+ 28 : 35,
+ 29 : 36,
+ 30 : 37,
+ 31 : 38,
+ 32 : 39,
+ 33 : 40,
+ 34 : 41,
+ 35 : 42,
+ 36 : 43,
+ 37 : 44,
+ 38 : 45,
+ 39 : 46,
+ 40 : 47,
+ 41 : 48,
+ 42 : 49,
+ 43 : 50,
+ 44 : 51,
+ 45 : 52,
+ 46 : 53,
+ 47 : 54,
+ 48 : 55,
+ 49 : 56,
+ 50 : 57,
+ 51 : 58,
+ 52 : 59,
+ 53 : 60,
+ 54 : 61,
+ 55 : 62,
+ 56 : 63,
}
_qsfp_ports = range(_qsfp_port_start, _ports_in_block + 1)
+
+ def get_presence(self, port_num):
+ # Check for invalid port_num
+ if port_num < self._port_start or port_num > self._port_end:
+ return False
+ path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present"
+ port_ps = path.format(self._port_to_i2c_mapping[port_num])
+
+
+ try:
+ reg_file = open(port_ps)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ try:
+ reg_value = reg_file.readline().rstrip()
+ except IOError as e:
+ time.sleep(1)
+
+ try:
+ reg_value = reg_file.readline().rstrip()
+ except IOError as e:
+ print "Error:try again to read file failed: %s %s" % (str(e), port_ps)
+ reg_file.close()
+ return False
+
+ reg_file.close()
+ if reg_value == '1':
+ return True
+
+ reg_file.close()
+ if reg_value == '1':
+ return True
+
+ return False
+
+ def init_global_port_presence(self):
+ for port_num in range(self.port_start, (self.port_end + 1)):
+ self._global_port_pres_dict[port_num] = '0'
+
+
def __init__(self):
eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom'
for x in range(self._port_start, self._port_end + 1):
port_eeprom_path = eeprom_path.format(self._port_to_i2c_mapping[x])
self._port_to_eeprom_mapping[x] = port_eeprom_path
-
- SfpUtilBase.__init__(self)
+
+ self.init_global_port_presence()
+ SfpUtilBase.__init__(self)
def reset(self, port_num):
# Check for invalid port_num
@@ -107,41 +152,88 @@ def reset(self, port_num):
reg_file.write('0')
reg_file.close()
return True
+
+ def set_low_power_mode(self, port_num, lpmode):
+ # Check for invalid port_num
+ if port_num < self._qsfp_port_start or port_num > self._port_end:
+ return False
+
+ pre_value = self.get_presence(port_num)
+ if pre_value == False:
+ return False
+
+ path = "/sys/bus/i2c/devices/{0}-0050/sfp_lpmode"
+ port_ps = path.format(self._port_to_i2c_mapping[port_num])
+
+ try:
+ reg_file = open(port_ps,'w')
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_file.seek(0)
+
+ if lpmode == 1:
+ reg_file.write('1')
+ elif lpmode == 0:
+ reg_file.write('0')
+ reg_file.close()
+
+ return True
- def set_low_power_mode(self, port_nuM, lpmode):
- raise NotImplementedError
def get_low_power_mode(self, port_num):
- raise NotImplementedError
-
- def get_presence(self, port_num):
# Check for invalid port_num
- if port_num < self._port_start or port_num > self._port_end:
- return False
- path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present"
+ if port_num < self._qsfp_port_start or port_num > self._port_end:
+ return False
+
+ pre_value = self.get_presence(port_num)
+ if pre_value == False:
+ return False
+
+ path = "/sys/bus/i2c/devices/{0}-0050/sfp_lpmode"
port_ps = path.format(self._port_to_i2c_mapping[port_num])
-
try:
reg_file = open(port_ps)
except IOError as e:
- print "Error: unable to open file: %s" % str(e)
+ print "Error: unable to open file:%s %s" % (str(e), port_ps)
+ return False
+
+ try:
+ reg_value = reg_file.readline().rstrip()
+ except IOError as e:
+ print "Error: unable to open file:%s %s" % (str(e), port_ps)
+ reg_file.close()
return False
+
+ reg_file.close()
- reg_value = reg_file.readline().rstrip()
if reg_value == '1':
return True
return False
-
+
def get_transceiver_change_event(self):
- """
- TODO: This function need to be implemented
- when decide to support monitoring SFP(Xcvrd)
- on this platform.
- """
- raise NotImplementedError
+ port_dict = {}
+ while True:
+ for port_num in range(self.port_start, (self.port_end + 1)):
+ presence = self.get_presence(port_num)
+
+ if(presence and self._global_port_pres_dict[port_num] == '0'):
+ self._global_port_pres_dict[port_num] = '1'
+ port_dict[port_num] = '1'
+ elif(not presence and
+ self._global_port_pres_dict[port_num] == '1'):
+ self._global_port_pres_dict[port_num] = '0'
+ port_dict[port_num] = '0'
+
+ if(len(port_dict) > 0):
+ return True, port_dict
+
+ time.sleep(0.5)
+
@property
def port_start(self):
diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/sensors.conf b/device/cig/x86_64-cig_cs6436_56p-r0/sensors.conf
old mode 100755
new mode 100644
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/port_config.ini b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/port_config.ini
index 55c8fb3dcf64..2b24bea93107 100644
--- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/port_config.ini
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/port_config.ini
@@ -31,5 +31,5 @@ Ethernet112 113,114,115,116 hundredGigE1/29 29 100000
Ethernet116 117,118,119,120 hundredGigE1/30 30 100000
Ethernet120 121,122,123,124 hundredGigE1/31 31 100000
Ethernet124 125,126,127,128 hundredGigE1/32 32 100000
-Ethernet128 128 tenGigE1/33 33 10000
-Ethernet129 129 tenGigE1/34 34 10000
+Ethernet128 129 tenGigE1/33 33 10000
+Ethernet129 128 tenGigE1/34 34 10000
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/sai_preinit_cmd.soc b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/sai_preinit_cmd.soc
new file mode 100644
index 000000000000..4d62900f898f
--- /dev/null
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/sai_preinit_cmd.soc
@@ -0,0 +1,2 @@
+m0 load 0 0x0 /usr/share/sonic/hwsku/linkscan_led_fw.bin
+m0 load 0 0x3800 /usr/share/sonic/hwsku/custom_led.bin
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/td3-s5232f-32x100G.config.bcm b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/td3-s5232f-32x100G.config.bcm
index e5b61b7f1b58..9b1035a942b3 100644
--- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/td3-s5232f-32x100G.config.bcm
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/td3-s5232f-32x100G.config.bcm
@@ -542,3 +542,5 @@ dport_map_port_66=127
dport_map_port_130=128
mmu_init_config="TD3-DEFAULT-LOSSLESS-P3P4"
+sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc
+
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/sai_preinit_cmd.soc b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/sai_preinit_cmd.soc
new file mode 100644
index 000000000000..4d62900f898f
--- /dev/null
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/sai_preinit_cmd.soc
@@ -0,0 +1,2 @@
+m0 load 0 0x0 /usr/share/sonic/hwsku/linkscan_led_fw.bin
+m0 load 0 0x3800 /usr/share/sonic/hwsku/custom_led.bin
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/td3-s5232f-32x100G.config.bcm b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/td3-s5232f-32x100G.config.bcm
index 533e19aca1c2..e2735ded69e8 100644
--- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/td3-s5232f-32x100G.config.bcm
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/td3-s5232f-32x100G.config.bcm
@@ -542,3 +542,4 @@ dport_map_port_66=127
dport_map_port_130=128
mmu_init_config="TD3-DEFAULT"
+sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/sai_preinit_cmd.soc b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/sai_preinit_cmd.soc
new file mode 100644
index 000000000000..4d62900f898f
--- /dev/null
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/sai_preinit_cmd.soc
@@ -0,0 +1,2 @@
+m0 load 0 0x0 /usr/share/sonic/hwsku/linkscan_led_fw.bin
+m0 load 0 0x3800 /usr/share/sonic/hwsku/custom_led.bin
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/td3-s5232f-96x10G+8x100G.config.bcm b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/td3-s5232f-96x10G+8x100G.config.bcm
index 0da20afc2203..0346c47749cb 100644
--- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/td3-s5232f-96x10G+8x100G.config.bcm
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/td3-s5232f-96x10G+8x100G.config.bcm
@@ -615,3 +615,4 @@ dport_map_port_66=127
dport_map_port_130=128
mmu_init_config="TD3-DEFAULT"
+sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/sai_preinit_cmd.soc b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/sai_preinit_cmd.soc
new file mode 100644
index 000000000000..4d62900f898f
--- /dev/null
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/sai_preinit_cmd.soc
@@ -0,0 +1,2 @@
+m0 load 0 0x0 /usr/share/sonic/hwsku/linkscan_led_fw.bin
+m0 load 0 0x3800 /usr/share/sonic/hwsku/custom_led.bin
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/td3-s5232f-96x25G+8x100G.config.bcm b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/td3-s5232f-96x25G+8x100G.config.bcm
index 47cbb41f4073..ca81379ae512 100644
--- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/td3-s5232f-96x25G+8x100G.config.bcm
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/td3-s5232f-96x25G+8x100G.config.bcm
@@ -615,3 +615,4 @@ dport_map_port_66=127
dport_map_port_130=128
mmu_init_config="TD3-DEFAULT"
+sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/installer.conf b/device/dell/x86_64-dellemc_s5232f_c3538-r0/installer.conf
index 925a32fc0c3a..924e0fb81963 100644
--- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/installer.conf
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/installer.conf
@@ -1,3 +1,2 @@
CONSOLE_PORT=0x3f8
CONSOLE_DEV=0
-CONSOLE_SPEED=115200
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/led_proc_init.soc b/device/dell/x86_64-dellemc_s5232f_c3538-r0/led_proc_init.soc
index 7105381ecdbc..098d5d4fd131 100644
--- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/led_proc_init.soc
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/led_proc_init.soc
@@ -2,8 +2,8 @@
#
#
#Led0
-#led stop
-m0 load 0 0x0 /usr/share/sonic/hwsku/linkscan_led_fw.bin
+led stop
+#m0 load 0 0x0 /usr/share/sonic/hwsku/linkscan_led_fw.bin
m0 load 0 0x3800 /usr/share/sonic/hwsku/custom_led.bin
#led auto on
led start
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/psuutil.py b/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/psuutil.py
index bf10ef129626..c3e2a6d73bd0 100644
--- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/psuutil.py
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/psuutil.py
@@ -11,12 +11,13 @@
S5232F_MAX_PSUS = 2
-IPMI_PSU_DATA = "docker exec -it pmon ipmitool sdr list"
-IPMI_PSU_DATA_DOCKER = "ipmitool sdr list"
+IPMI_PSU1_DATA = "docker exec -it pmon ipmitool raw 0x04 0x2d 0x31 | awk '{print substr($0,9,1)}'"
+IPMI_PSU1_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x31 | awk '{print substr($0,9,1)}'"
+IPMI_PSU2_DATA = "docker exec -it pmon ipmitool raw 0x04 0x2d 0x32 | awk '{print substr($0,9,1)}'"
+IPMI_PSU2_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x32 | awk '{print substr($0,9,1)}'"
PSU_PRESENCE = "PSU{0}_stat"
# Use this for older firmware
# PSU_PRESENCE="PSU{0}_prsnt"
-ipmi_sdr_list = ""
try:
@@ -42,30 +43,26 @@ def isDockerEnv(self):
def get_pmc_register(self, reg_name):
status = 1
- global ipmi_sdr_list
- ipmi_dev_node = "/dev/pmi0"
- ipmi_cmd = IPMI_PSU_DATA
+ ipmi_cmd_1 = IPMI_PSU1_DATA
+ ipmi_cmd_2 = IPMI_PSU1_DATA
dockerenv = self.isDockerEnv()
if dockerenv == True:
- ipmi_cmd = IPMI_PSU_DATA_DOCKER
-
- status, ipmi_sdr_list = commands.getstatusoutput(ipmi_cmd)
+ if index == 1:
+ status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU1_DATA_DOCKER)
+ elif index == 2:
+ status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU2_DATA_DOCKER)
+ else:
+ if index == 1:
+ status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU1_DATA)
+ elif index == 2:
+ status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU2_DATA)
if status:
- logging.error('Failed to execute:' + ipmi_sdr_list)
- sys.exit(0)
-
- for item in ipmi_sdr_list.split("\n"):
- if reg_name in item:
- output = item.strip()
-
- if not output:
- print('\nFailed to fetch: ' + reg_name + ' sensor ')
+ logging.error('Failed to execute ipmitool')
sys.exit(0)
- output = output.split('|')[1]
+ output = ipmi_sdr_list
- logging.basicConfig(level=logging.DEBUG)
return output
def get_num_psus(self):
@@ -86,8 +83,26 @@ def get_psu_status(self, index):
"""
# Until psu_status is implemented this is hardcoded temporarily
- status = 1
- return status
+ psu_status = 'f'
+ ret_status = 1
+ dockerenv = self.isDockerEnv()
+ if dockerenv == True:
+ if index == 1:
+ ret_status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU1_DATA_DOCKER)
+ elif index == 2:
+ ret_status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU2_DATA_DOCKER)
+ else:
+ if index == 1:
+ ret_status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU1_DATA)
+ elif index == 2:
+ ret_status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU2_DATA)
+
+ if ret_status:
+ logging.error('Failed to execute ipmitool : ')
+ sys.exit(0)
+
+ psu_status = ipmi_sdr_list
+ return (not int(psu_status, 16) > 1)
def get_psu_presence(self, index):
"""
@@ -96,12 +111,23 @@ def get_psu_presence(self, index):
:param index: An integer, index of the PSU of which to query status
:return: Boolean, True if PSU is plugged, False if not
"""
- status = 0
- psu_reg_name = PSU_PRESENCE.format(index)
- psu_status = int(self.get_pmc_register(psu_reg_name), 16)
- if (psu_status != 'ERR'):
- # Check for PSU presence
- if (psu_status == 0x00):
- status = 1
- return status
+ psu_status = '0'
+ ret_status = 1
+ dockerenv = self.isDockerEnv()
+ if dockerenv == True:
+ if index == 1:
+ ret_status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU1_DATA_DOCKER)
+ elif index == 2:
+ ret_status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU2_DATA_DOCKER)
+ else:
+ if index == 1:
+ ret_status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU1_DATA)
+ elif index == 2:
+ ret_status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU2_DATA)
+
+ if ret_status:
+ logging.error('Failed to execute ipmitool : ')
+ sys.exit(0)
+ psu_status = ipmi_sdr_list
+ return (int(psu_status, 16) & 1)
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/sfputil.py
index 192fb80f6c56..62dc5cb9c34b 100644
--- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/sfputil.py
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/sfputil.py
@@ -8,20 +8,48 @@
import sys
import getopt
import time
+ import io
from sonic_sfp.sfputilbase import SfpUtilBase
from os import *
from mmap import *
-
+ from sonic_sfp.sff8436 import sff8436InterfaceId
+ from sonic_sfp.sff8436 import sff8436Dom
+ from sonic_sfp.sff8472 import sff8472Dom
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))
+QSFP_DOM_REV_OFFSET = 1
+QSFP_DOM_REV_WIDTH = 1
+QSFP_TEMPE_OFFSET = 22
+QSFP_TEMPE_WIDTH = 2
+QSFP_VOLT_OFFSET = 26
+QSFP_VOLT_WIDTH = 2
+QSFP_CHANNL_MON_OFFSET = 34
+QSFP_CHANNL_MON_WIDTH = 16
+QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24
+QSFP_MODULE_THRESHOLD_OFFSET = 128
+QSFP_MODULE_THRESHOLD_WIDTH = 24
+QSFP_CHANNL_THRESHOLD_OFFSET = 176
+QSFP_CHANNL_THRESHOLD_WIDTH = 16
+QSFP_CHANNL_MON_MASK_OFFSET = 242
+QSFP_CHANNL_MON_MASK_WIDTH = 4
+
+SFP_TEMPE_OFFSET = 96
+SFP_TEMPE_WIDTH = 2
+SFP_VOLT_OFFSET = 98
+SFP_VOLT_WIDTH = 2
+SFP_MODULE_THRESHOLD_OFFSET = 0
+SFP_MODULE_THRESHOLD_WIDTH = 56
+
+XCVR_DOM_CAPABILITY_OFFSET = 92
+XCVR_DOM_CAPABILITY_WIDTH = 1
class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""
PORT_START = 1
- PORT_END = 64
- PORTS_IN_BLOCK = 64
+ PORT_END = 34
+ PORTS_IN_BLOCK = 32
BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0"
@@ -112,6 +140,11 @@ def get_presence(self, port_num):
# Mask off 4th bit for presence
mask = (1 << 4)
+ # Mask off 1st bit for presence 33,34
+ if (port_num > 32):
+ mask = (1 << 0)
+
+
# ModPrsL is active low
if reg_value & mask == 0:
return True
@@ -208,8 +241,11 @@ def reset(self, port_num):
return True
- def get_transceiver_change_event(self):
+ def get_transceiver_change_event(self, timeout=0):
port_dict = {}
+ sleep_time_ms = 500 # Poll interval, in milliseconds
+ sleep_time = sleep_time_ms / 1000.0
+ elapsed_time_ms = 0
while True:
for port_num in range(self.port_start, (self.port_end + 1)):
presence = self.get_presence(port_num)
@@ -222,6 +258,312 @@ def get_transceiver_change_event(self):
port_dict[port_num] = '0'
if(len(port_dict) > 0):
- return True, port_dict
+ break
+
+ if len(port_dict) > 0:
+ break
+ if timeout != 0:
+ elapsed_time_ms += sleep_time_ms
+ if elapsed_time_ms > timeout:
+ break
+ time.sleep(sleep_time)
+
+ return True, port_dict
+
+
+ def get_transceiver_dom_info_dict(self, port_num):
+ transceiver_dom_info_dict = {}
+
+ dom_info_dict_keys = ['temperature', 'voltage', 'rx1power',
+ 'rx2power', 'rx3power', 'rx4power',
+ 'tx1bias', 'tx2bias', 'tx3bias',
+ 'tx4bias', 'tx1power', 'tx2power',
+ 'tx3power', 'tx4power',
+ ]
+ transceiver_dom_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A')
+
+ if port_num in self.qsfp_ports:
+ offset = 0
+ offset_xcvr = 128
+ file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR)
+ if not self._sfp_eeprom_present(file_path, 0):
+ return None
+
+ try:
+ sysfsfile_eeprom = io.open(file_path, mode="rb", buffering=0)
+ except IOError:
+ print("Error: reading sysfs file %s" % file_path)
+ return None
+
+ sfpd_obj = sff8436Dom()
+ if sfpd_obj is None:
+ return transceiver_dom_info_dict
+
+ sfpi_obj = sff8436InterfaceId()
+ if sfpi_obj is None:
+ return transceiver_dom_info_dict
+
+ # QSFP capability byte parse, through this byte can know whether it support tx_power or not.
+ # TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436,
+ # need to add more code for determining the capability and version compliance
+ # in SFF-8636 dom capability definitions evolving with the versions.
+ qsfp_dom_capability_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH)
+ if qsfp_dom_capability_raw is not None:
+ qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0)
+ else:
+ return transceiver_dom_info_dict
+
+ dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH)
+ if dom_temperature_raw is not None:
+ dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0)
+ else:
+ return transceiver_dom_info_dict
+
+ dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH)
+ if dom_voltage_raw is not None:
+ dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
+ else:
+ return transceiver_dom_info_dict
+
+ qsfp_dom_rev_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_DOM_REV_OFFSET), QSFP_DOM_REV_WIDTH)
+ if qsfp_dom_rev_raw is not None:
+ qsfp_dom_rev_data = sfpd_obj.parse_sfp_dom_rev(qsfp_dom_rev_raw, 0)
+ else:
+ return transceiver_dom_info_dict
+
+ transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
+ transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
+
+ # The tx_power monitoring is only available on QSFP which compliant with SFF-8636
+ # and claimed that it support tx_power with one indicator bit.
+ dom_channel_monitor_data = {}
+ qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value']
+ qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['value']
+ if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')):
+ dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WIDTH)
+ if dom_channel_monitor_raw is not None:
+ dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0)
+ else:
+ return transceiver_dom_info_dict
+
+ transceiver_dom_info_dict['tx1power'] = 'N/A'
+ transceiver_dom_info_dict['tx2power'] = 'N/A'
+ transceiver_dom_info_dict['tx3power'] = 'N/A'
+ transceiver_dom_info_dict['tx4power'] = 'N/A'
+ else:
+ dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH)
+ if dom_channel_monitor_raw is not None:
+ dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0)
+ else:
+ return None
+
+ transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value']
+ transceiver_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value']
+ transceiver_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value']
+ transceiver_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value']
+
+ try:
+ sysfsfile_eeprom.close()
+ except IOError:
+ print("Error: closing sysfs file %s" % file_path)
+ return None
+
+ transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
+ transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
+ transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value']
+ transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value']
+ transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value']
+ transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value']
+ transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value']
+ transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value']
+ transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value']
+ transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value']
+
+ else:
+ offset = 256
+ file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR)
+ if not self._sfp_eeprom_present(file_path, 0):
+ return None
+
+ try:
+ sysfsfile_eeprom = io.open(file_path,"rb",0)
+ except IOError:
+ print("Error: reading sysfs file %s" % file_path)
+ return None
+
+ sfpd_obj = sff8472Dom(None,1)
+ if sfpd_obj is None:
+ return transceiver_dom_info_dict
+
+ dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET),
+ SFP_TEMPE_WIDTH)
+ if dom_temperature_raw is not None:
+ dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0)
+ else:
+ return transceiver_dom_info_dict
+
+ dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_VOLT_OFFSET),
+ SFP_VOLT_WIDTH)
+ if dom_voltage_raw is not None:
+ dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
+ else:
+ return transceiver_dom_info_dict
+
+ dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_MODULE_THRESHOLD_OFFSET),
+ SFP_MODULE_THRESHOLD_WIDTH)
+ if dom_channel_monitor_raw is not None:
+ dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0)
+ else:
+ return transceiver_dom_info_dict
+
+ try:
+ sysfsfile_eeprom.close()
+ except IOError:
+ print("Error: closing sysfs file %s" % file_path)
+ return None
+
+ transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
+ transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
+ transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value']
+ transceiver_dom_info_dict['rx2power'] = 'N/A'
+ transceiver_dom_info_dict['rx3power'] = 'N/A'
+ transceiver_dom_info_dict['rx4power'] = 'N/A'
+ transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value']
+ transceiver_dom_info_dict['tx2bias'] = 'N/A'
+ transceiver_dom_info_dict['tx3bias'] = 'N/A'
+ transceiver_dom_info_dict['tx4bias'] = 'N/A'
+ transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value']
+ transceiver_dom_info_dict['tx2power'] = 'N/A'
+ transceiver_dom_info_dict['tx3power'] = 'N/A'
+ transceiver_dom_info_dict['tx4power'] = 'N/A'
+
+ return transceiver_dom_info_dict
+
+ def get_transceiver_dom_threshold_info_dict(self, port_num):
+ transceiver_dom_threshold_info_dict = {}
+ dom_info_dict_keys = ['temphighalarm', 'temphighwarning',
+ 'templowalarm', 'templowwarning',
+ 'vcchighalarm', 'vcchighwarning',
+ 'vcclowalarm', 'vcclowwarning',
+ 'rxpowerhighalarm', 'rxpowerhighwarning',
+ 'rxpowerlowalarm', 'rxpowerlowwarning',
+ 'txpowerhighalarm', 'txpowerhighwarning',
+ 'txpowerlowalarm', 'txpowerlowwarning',
+ 'txbiashighalarm', 'txbiashighwarning',
+ 'txbiaslowalarm', 'txbiaslowwarning'
+ ]
+ transceiver_dom_threshold_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A')
+
+ if port_num in self.qsfp_ports:
+ file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR)
+ if not self._sfp_eeprom_present(file_path, 0):
+ return None
+
+ try:
+ sysfsfile_eeprom = io.open(file_path, mode="rb", buffering=0)
+ except IOError:
+ print("Error: reading sysfs file %s" % file_path)
+ return None
+
+ sfpd_obj = sff8436Dom()
+ if sfpd_obj is None:
+ return transceiver_dom_threshold_info_dict
+
+ # Dom Threshold data starts from offset 384
+ # Revert offset back to 0 once data is retrieved
+ offset = 384
+ dom_module_threshold_raw = self._read_eeprom_specific_bytes(
+ sysfsfile_eeprom,
+ (offset + QSFP_MODULE_THRESHOLD_OFFSET),
+ QSFP_MODULE_THRESHOLD_WIDTH)
+ if dom_module_threshold_raw is not None:
+ dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0)
+ else:
+ return transceiver_dom_threshold_info_dict
+
+ dom_channel_threshold_raw = self._read_eeprom_specific_bytes(
+ sysfsfile_eeprom,
+ (offset + QSFP_CHANNL_THRESHOLD_OFFSET),
+ QSFP_CHANNL_THRESHOLD_WIDTH)
+ if dom_channel_threshold_raw is not None:
+ dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values(dom_channel_threshold_raw, 0)
+ else:
+ return transceiver_dom_threshold_info_dict
+
+ try:
+ sysfsfile_eeprom.close()
+ except IOError:
+ print("Error: closing sysfs file %s" % file_path)
+ return None
+
+ # Threshold Data
+ transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value']
+ transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value']
+ transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value']
+ transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value']
+ transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value']
+ transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value']
+ transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value']
+ transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value']
+ transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value']
+ transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value']
+ transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value']
+ transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value']
+ transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['TxBiasHighAlarm']['value']
+ transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['TxBiasHighWarning']['value']
+ transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['TxBiasLowAlarm']['value']
+ transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['TxBiasLowWarning']['value']
- time.sleep(0.5)
+ else:
+ offset = 256
+ file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR)
+ if not self._sfp_eeprom_present(file_path, 0):
+ return None
+
+ try:
+ sysfsfile_eeprom = io.open(file_path,"rb",0)
+ except IOError:
+ print("Error: reading sysfs file %s" % file_path)
+ return None
+
+ sfpd_obj = sff8472Dom(None,1)
+ if sfpd_obj is None:
+ return transceiver_dom_threshold_info_dict
+
+ dom_module_threshold_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom,
+ (offset + SFP_MODULE_THRESHOLD_OFFSET), SFP_MODULE_THRESHOLD_WIDTH)
+
+ if dom_module_threshold_raw is not None:
+ dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0)
+ else:
+ return transceiver_dom_threshold_info_dict
+
+ try:
+ sysfsfile_eeprom.close()
+ except IOError:
+ print("Error: closing sysfs file %s" % file_path)
+ return None
+
+ #Threshold Data
+ transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value']
+ transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value']
+ transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value']
+ transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value']
+ transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VoltageHighAlarm']['value']
+ transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value']
+ transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VoltageHighWarning']['value']
+ transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value']
+ transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value']
+ transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value']
+ transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value']
+ transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value']
+ transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value']
+ transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value']
+ transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value']
+ transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value']
+ transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value']
+ transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value']
+ transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value']
+ transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value']
+
+ return transceiver_dom_threshold_info_dict
diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/pmon_daemon_control.json b/device/dell/x86_64-dellemc_s5232f_c3538-r0/pmon_daemon_control.json
index 94592fa8cebc..44871c057e82 100644
--- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/pmon_daemon_control.json
+++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/pmon_daemon_control.json
@@ -1,3 +1,4 @@
{
- "skip_ledd": true
+ "skip_ledd": true,
+ "skip_thermalctld": true
}
diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/platform_components.json b/device/mellanox/x86_64-mlnx_msn2010-r0/platform_components.json
new file mode 100644
index 000000000000..775c6e22cf5c
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn2010-r0/platform_components.json
@@ -0,0 +1,10 @@
+{
+ "chassis": {
+ "x86_64-mlnx_msn2010-r0": {
+ "component": {
+ "BIOS": { },
+ "CPLD": { }
+ }
+ }
+ }
+}
diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/platform_components.json b/device/mellanox/x86_64-mlnx_msn2100-r0/platform_components.json
new file mode 100644
index 000000000000..6a6a74301cbc
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn2100-r0/platform_components.json
@@ -0,0 +1,10 @@
+{
+ "chassis": {
+ "x86_64-mlnx_msn2100-r0": {
+ "component": {
+ "BIOS": { },
+ "CPLD": { }
+ }
+ }
+ }
+}
diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/platform_components.json b/device/mellanox/x86_64-mlnx_msn2410-r0/platform_components.json
new file mode 100644
index 000000000000..77da35ce5818
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn2410-r0/platform_components.json
@@ -0,0 +1,10 @@
+{
+ "chassis": {
+ "x86_64-mlnx_msn2410-r0": {
+ "component": {
+ "BIOS": { },
+ "CPLD": { }
+ }
+ }
+ }
+}
diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2
index 8c3cac4b80b8..5529ee3d8598 100644
--- a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2
+++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2
@@ -1,8 +1,8 @@
{% set default_cable = '5m' %}
-{% set ingress_lossless_pool_size = '4194304' %}
-{% set ingress_lossy_pool_size = '7340032' %}
-{% set egress_lossless_pool_size = '16777152' %}
-{% set egress_lossy_pool_size = '7340032' %}
+{% set ingress_lossless_pool_size = '5029836' %}
+{% set ingress_lossy_pool_size = '5029836' %}
+{% set egress_lossless_pool_size = '14024599' %}
+{% set egress_lossy_pool_size = '5029836' %}
{%- macro generate_port_lists(PORT_ALL) %}
{# Generate list of ports #}
diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2
index 45433b1b2641..f418e2ffa1db 100644
--- a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2
+++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2
@@ -1,8 +1,8 @@
{% set default_cable = '5m' %}
-{% set ingress_lossless_pool_size = '2097152' %}
-{% set ingress_lossy_pool_size = '5242880' %}
-{% set egress_lossless_pool_size = '16777152' %}
-{% set egress_lossy_pool_size = '5242880' %}
+{% set ingress_lossless_pool_size = '2097100' %}
+{% set ingress_lossy_pool_size = '2097100' %}
+{% set egress_lossless_pool_size = '14024599' %}
+{% set egress_lossy_pool_size = '2097100' %}
{%- macro generate_port_lists(PORT_ALL) %}
{# Generate list of ports #}
diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/port_config.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/port_config.ini
index 345e6a206731..8bc48269d163 100644
--- a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/port_config.ini
+++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/port_config.ini
@@ -1,37 +1,37 @@
-# name lanes speed alias index
-Ethernet0 0,1,2,3 100000 etp1 1
-Ethernet4 4,5,6,7 100000 etp2 2
-Ethernet8 8,9,10,11 100000 etp3 3
-Ethernet12 12,13,14,15 100000 etp4 4
-Ethernet16 16,17,18,19 100000 etp5 5
-Ethernet20 20,21,22,23 100000 etp6 6
-Ethernet24 24,25,26,27 100000 etp7 7
-Ethernet28 28,29,30,31 100000 etp8 8
-Ethernet32 32,33,34,35 100000 etp9 9
-Ethernet36 36,37,38,39 100000 etp10 10
-Ethernet40 40,41,42,43 100000 etp11 11
-Ethernet44 44,45,46,47 100000 etp12 12
-Ethernet48 48,49,50,51 100000 etp13 13
-Ethernet52 52,53,54,55 100000 etp14 14
-Ethernet56 56,57,58,59 100000 etp15 15
-Ethernet60 60,61,62,63 100000 etp16 16
-Ethernet64 64,65,66,67 100000 etp17 17
-Ethernet68 68,69,70,71 100000 etp18 18
-Ethernet72 72,73,74,75 100000 etp19 19
-Ethernet76 76,77,78,79 100000 etp20 20
-Ethernet80 80,81,82,83 100000 etp21 21
-Ethernet84 84,85,86,87 100000 etp22 22
-Ethernet88 88,89,90,91 100000 etp23 23
-Ethernet92 92,93,94,95 100000 etp24 24
-Ethernet96 96,97,98,99 100000 etp25 25
-Ethernet100 100,101,102,103 100000 etp26 26
-Ethernet104 104,105,106,107 100000 etp27 27
-Ethernet108 108,109,110,111 100000 etp28 28
-Ethernet112 112,113 50000 etp29a 29
-Ethernet114 114,115 50000 etp29b 29
-Ethernet116 116,117 50000 etp30a 30
-Ethernet118 118,119 50000 etp30b 30
-Ethernet120 120,121 50000 etp31a 31
-Ethernet122 122,123 50000 etp31b 31
-Ethernet124 124,125 50000 etp32a 32
-Ethernet126 126,127 50000 etp32b 32
\ No newline at end of file
+# name lanes alias index speed
+Ethernet0 0,1,2,3 etp1 0 100000
+Ethernet4 4,5,6,7 etp2 1 100000
+Ethernet8 8,9,10,11 etp3 2 100000
+Ethernet12 12,13,14,15 etp4 3 100000
+Ethernet16 16,17,18,19 etp5 4 100000
+Ethernet20 20,21,22,23 etp6 5 100000
+Ethernet24 24,25,26,27 etp7 6 100000
+Ethernet28 28,29,30,31 etp8 7 100000
+Ethernet32 32,33,34,35 etp9 8 100000
+Ethernet36 36,37,38,39 etp10 9 100000
+Ethernet40 40,41,42,43 etp11 10 100000
+Ethernet44 44,45,46,47 etp12 11 100000
+Ethernet48 48,49,50,51 etp13 12 100000
+Ethernet52 52,53,54,55 etp14 13 100000
+Ethernet56 56,57,58,59 etp15 14 100000
+Ethernet60 60,61,62,63 etp16 15 100000
+Ethernet64 64,65,66,67 etp17 16 100000
+Ethernet68 68,69,70,71 etp18 17 100000
+Ethernet72 72,73,74,75 etp19 18 100000
+Ethernet76 76,77,78,79 etp20 19 100000
+Ethernet80 80,81,82,83 etp21 20 100000
+Ethernet84 84,85,86,87 etp22 21 100000
+Ethernet88 88,89,90,91 etp23 22 100000
+Ethernet92 92,93,94,95 etp24 23 100000
+Ethernet96 96,97,98,99 etp25 24 100000
+Ethernet100 100,101,102,103 etp26 25 100000
+Ethernet104 104,105,106,107 etp27 26 100000
+Ethernet108 108,109,110,111 etp28 27 100000
+Ethernet112 112,113 etp29a 28 50000
+Ethernet114 114,115 etp29b 28 50000
+Ethernet116 116,117 etp30a 29 50000
+Ethernet118 118,119 etp30b 29 50000
+Ethernet120 120,121 etp31a 30 50000
+Ethernet122 122,123 etp31b 30 50000
+Ethernet124 124,125 etp32a 31 50000
+Ethernet126 126,127 etp32b 31 50000
diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/port_config.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/port_config.ini
index 9e01da79f449..f9f465f1a3ea 100644
--- a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/port_config.ini
+++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/port_config.ini
@@ -1,57 +1,57 @@
-# name lanes speed alias index
-Ethernet0 0,1 50000 etp1a 1
-Ethernet2 2,3 50000 etp1b 1
-Ethernet4 4,5 50000 etp2a 2
-Ethernet6 6,7 50000 etp2b 2
-Ethernet8 8,9 50000 etp3a 3
-Ethernet10 10,11 50000 etp3b 3
-Ethernet12 12,13 50000 etp4a 4
-Ethernet14 14,15 50000 etp4b 4
-Ethernet16 16,17 50000 etp5a 5
-Ethernet18 18,19 50000 etp5b 5
-Ethernet20 20,21 50000 etp6a 6
-Ethernet22 22,23 50000 etp6b 6
-Ethernet24 24,25,26,27 100000 etp7 7
-Ethernet28 28,29,30,31 100000 etp8 8
-Ethernet32 32,33,34,35 100000 etp9 9
-Ethernet36 36,37,38,39 100000 etp10 10
-Ethernet40 40,41 50000 etp11a 11
-Ethernet42 42,43 50000 etp11b 11
-Ethernet44 44,45 50000 etp12a 12
-Ethernet46 46,47 50000 etp12b 12
-Ethernet48 48,49 50000 etp13a 13
-Ethernet50 50,51 50000 etp13b 13
-Ethernet52 52,53 50000 etp14a 14
-Ethernet54 54,55 50000 etp14b 14
-Ethernet56 56,57 50000 etp15a 15
-Ethernet58 58,59 50000 etp15b 15
-Ethernet60 60,61 50000 etp16a 16
-Ethernet62 62,63 50000 etp16b 16
-Ethernet64 64,65 50000 etp17a 17
-Ethernet66 66,67 50000 etp17b 17
-Ethernet68 68,69 50000 etp18a 18
-Ethernet70 70,71 50000 etp18b 18
-Ethernet72 72,73 50000 etp19a 19
-Ethernet74 74,75 50000 etp19b 19
-Ethernet76 76,77 50000 etp20a 20
-Ethernet78 78,79 50000 etp20b 20
-Ethernet80 80,81 50000 etp21a 21
-Ethernet82 82,83 50000 etp21b 21
-Ethernet84 84,85 50000 etp22a 22
-Ethernet86 86,87 50000 etp22b 22
-Ethernet88 88,89,90,91 100000 etp23 23
-Ethernet92 92,93,94,95 100000 etp24 24
-Ethernet96 96,97,98,99 100000 etp25 25
-Ethernet100 100,101,102,103 100000 etp26 26
-Ethernet104 104,105 50000 etp27a 27
-Ethernet106 106,107 50000 etp27b 27
-Ethernet108 108,109 50000 etp28a 28
-Ethernet110 110,111 50000 etp28b 28
-Ethernet112 112,113 50000 etp29a 29
-Ethernet114 114,115 50000 etp29b 29
-Ethernet116 116,117 50000 etp30a 30
-Ethernet118 118,119 50000 etp30b 30
-Ethernet120 120,121 50000 etp31a 31
-Ethernet122 122,123 50000 etp31b 31
-Ethernet124 124,125 50000 etp32a 32
-Ethernet126 126,127 50000 etp32b 32
+# name lanes alias index speed
+Ethernet0 0,1 etp1a 0 50000
+Ethernet2 2,3 etp1b 0 50000
+Ethernet4 4,5 etp2a 1 50000
+Ethernet6 6,7 etp2b 1 50000
+Ethernet8 8,9 etp3a 2 50000
+Ethernet10 10,11 etp3b 2 50000
+Ethernet12 12,13 etp4a 3 50000
+Ethernet14 14,15 etp4b 3 50000
+Ethernet16 16,17 etp5a 4 50000
+Ethernet18 18,19 etp5b 4 50000
+Ethernet20 20,21 etp6a 5 50000
+Ethernet22 22,23 etp6b 5 50000
+Ethernet24 24,25,26,27 etp7 6 100000
+Ethernet28 28,29,30,31 etp8 7 100000
+Ethernet32 32,33,34,35 etp9 8 100000
+Ethernet36 36,37,38,39 etp10 9 100000
+Ethernet40 40,41 etp11a 10 50000
+Ethernet42 42,43 etp11b 10 50000
+Ethernet44 44,45 etp12a 11 50000
+Ethernet46 46,47 etp12b 11 50000
+Ethernet48 48,49 etp13a 12 50000
+Ethernet50 50,51 etp13b 12 50000
+Ethernet52 52,53 etp14a 13 50000
+Ethernet54 54,55 etp14b 13 50000
+Ethernet56 56,57 etp15a 14 50000
+Ethernet58 58,59 etp15b 14 50000
+Ethernet60 60,61 etp16a 15 50000
+Ethernet62 62,63 etp16b 15 50000
+Ethernet64 64,65 etp17a 16 50000
+Ethernet66 66,67 etp17b 16 50000
+Ethernet68 68,69 etp18a 17 50000
+Ethernet70 70,71 etp18b 17 50000
+Ethernet72 72,73 etp19a 18 50000
+Ethernet74 74,75 etp19b 18 50000
+Ethernet76 76,77 etp20a 19 50000
+Ethernet78 78,79 etp20b 19 50000
+Ethernet80 80,81 etp21a 20 50000
+Ethernet82 82,83 etp21b 20 50000
+Ethernet84 84,85 etp22a 21 50000
+Ethernet86 86,87 etp22b 21 50000
+Ethernet88 88,89,90,91 etp23 22 100000
+Ethernet92 92,93,94,95 etp24 23 100000
+Ethernet96 96,97,98,99 etp25 24 100000
+Ethernet100 100,101,102,103 etp26 25 100000
+Ethernet104 104,105 etp27a 26 50000
+Ethernet106 106,107 etp27b 26 50000
+Ethernet108 108,109 etp28a 27 50000
+Ethernet110 110,111 etp28b 27 50000
+Ethernet112 112,113 etp29a 28 50000
+Ethernet114 114,115 etp29b 28 50000
+Ethernet116 116,117 etp30a 29 50000
+Ethernet118 118,119 etp30b 29 50000
+Ethernet120 120,121 etp31a 30 50000
+Ethernet122 122,123 etp31b 30 50000
+Ethernet124 124,125 etp32a 31 50000
+Ethernet126 126,127 etp32b 31 50000
diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/platform_components.json b/device/mellanox/x86_64-mlnx_msn2700-r0/platform_components.json
new file mode 100644
index 000000000000..2a6069414786
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn2700-r0/platform_components.json
@@ -0,0 +1,10 @@
+{
+ "chassis": {
+ "x86_64-mlnx_msn2700-r0": {
+ "component": {
+ "BIOS": { },
+ "CPLD": { }
+ }
+ }
+ }
+}
diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/eeprom.py
index 63303c13a244..c9ae1a335421 100644
--- a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/eeprom.py
+++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/eeprom.py
@@ -21,6 +21,7 @@
from cStringIO import StringIO
from sonic_eeprom import eeprom_base
from sonic_eeprom import eeprom_tlvinfo
+ from sonic_device_util import get_machine_info
import subprocess
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
@@ -34,6 +35,14 @@ def log_error(msg):
syslog.syslog(syslog.LOG_ERR, msg)
syslog.closelog()
+
+machine_info = get_machine_info()
+onie_platform = machine_info['onie_platform']
+if 'simx' in onie_platform:
+ platform_path = os.path.join('/usr/share/sonic/device', onie_platform)
+ subprocess.check_call(['/usr/bin/xxd', '-r', '-p', 'syseeprom.hex', 'syseeprom.bin'], cwd=platform_path)
+ CACHE_FILE = os.path.join(platform_path, 'syseeprom.bin')
+
class board(eeprom_tlvinfo.TlvInfoDecoder):
_TLV_INFO_MAX_LEN = 256
@@ -45,12 +54,12 @@ def __init__(self, name, path, cpld_root, ro):
time.sleep(1)
else:
break
-
+
if not (os.path.exists(EEPROM_SYMLINK) or os.path.isfile(CACHE_FILE)):
log_error("Nowhere to read syseeprom from! No symlink or cache file found")
raise RuntimeError("No syseeprom symlink or cache file found")
- self.eeprom_path = EEPROM_SYMLINK
+ self.eeprom_path = EEPROM_SYMLINK if 'simx' not in onie_platform else CACHE_FILE
super(board, self).__init__(self.eeprom_path, 0, '', True)
def decode_eeprom(self, e):
@@ -60,3 +69,4 @@ def decode_eeprom(self, e):
decode_output = sys.stdout.getvalue()
sys.stdout = original_stdout
print(decode_output.replace('\0', ''))
+
diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py
index c11675766d3f..f9b35b8e74e7 100644
--- a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py
+++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py
@@ -18,14 +18,19 @@
PMAOS_ENABLE = 1
PMAOS_DISABLE = 2
+PORT_TYPE_CPU = 4
PORT_TYPE_NVE = 8
PORT_TYPE_OFFSET = 28
PORT_TYPE_MASK = 0xF0000000
NVE_MASK = PORT_TYPE_MASK & (PORT_TYPE_NVE << PORT_TYPE_OFFSET)
+CPU_MASK = PORT_TYPE_MASK & (PORT_TYPE_CPU << PORT_TYPE_OFFSET)
def is_nve(port):
return (port & NVE_MASK) != 0
+def is_cpu(port):
+ return (port & CPU_MASK) != 0
+
def is_port_admin_status_up(log_port):
oper_state_p = new_sx_port_oper_state_t_p()
admin_state_p = new_sx_port_admin_state_t_p()
@@ -57,6 +62,7 @@ def get_log_ports(handle, sfp_module):
for i in range(0, port_cnt):
port_attributes = sx_port_attributes_t_arr_getitem(port_attributes_list, i)
if is_nve(int(port_attributes.log_port)) == False \
+ and is_cpu(int(port_attributes.log_port)) == False \
and port_attributes.port_mapping.module_port == sfp_module \
and is_port_admin_status_up(port_attributes.log_port):
log_port_list.append(port_attributes.log_port)
diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py
index e41ac2924da2..b5f2a335b09c 100644
--- a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py
+++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py
@@ -22,8 +22,6 @@
SFP_I2C_PAGE_SIZE = 256
# parameters for DB connection
-REDIS_HOSTNAME = "localhost"
-REDIS_PORT = 6379
REDIS_TIMEOUT_USECS = 0
# parameters for SFP presence
@@ -43,7 +41,7 @@
# magic code defnition for port number, qsfp port position of each hwsku
# port_position_tuple = (PORT_START, QSFP_PORT_START, PORT_END, PORT_IN_BLOCK, EEPROM_OFFSET)
-hwsku_dict = {'ACS-MSN2700': 0, 'Mellanox-SN2700': 0, 'Mellanox-SN2700-D48C8': 0, "LS-SN2700":0, 'ACS-MSN2740': 0, 'ACS-MSN2100': 1, 'ACS-MSN2410': 2, 'ACS-MSN2010': 3, 'ACS-MSN3700': 0, 'ACS-MSN3700C': 0, 'ACS-MSN3800': 4}
+hwsku_dict = {'ACS-MSN2700': 0, 'Mellanox-SN2700': 0, 'Mellanox-SN2700-D48C8': 0, 'LS-SN2700': 0, 'ACS-MSN2740': 0, 'ACS-MSN2100': 1, 'ACS-MSN2410': 2, 'ACS-MSN2010': 3, 'ACS-MSN3700': 0, 'ACS-MSN3700C': 0, 'ACS-MSN3800': 4, 'Mellanox-SN3800-D112C8': 4, 'ACS-MSN4700': 0}
port_position_tuple_list = [(0, 0, 31, 32, 1), (0, 0, 15, 16, 1), (0, 48, 55, 56, 1), (0, 18, 21, 22, 1), (0, 0, 63, 64, 1)]
def log_info(msg, also_print_to_console=False):
@@ -190,10 +188,9 @@ def get_transceiver_change_event(self, timeout=0):
if self.db_sel == None:
from swsscommon import swsscommon
- self.state_db = swsscommon.DBConnector(swsscommon.STATE_DB,
- REDIS_HOSTNAME,
- REDIS_PORT,
- REDIS_TIMEOUT_USECS)
+ self.state_db = swsscommon.DBConnector("STATE_DB",
+ REDIS_TIMEOUT_USECS,
+ True)
# Subscribe to state table for SFP change notifications
self.db_sel = swsscommon.Select()
diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/platform_components.json b/device/mellanox/x86_64-mlnx_msn2740-r0/platform_components.json
new file mode 100644
index 000000000000..7964d9cb8713
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn2740-r0/platform_components.json
@@ -0,0 +1,10 @@
+{
+ "chassis": {
+ "x86_64-mlnx_msn2740-r0": {
+ "component": {
+ "BIOS": { },
+ "CPLD": { }
+ }
+ }
+ }
+}
diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t0.j2
index d40bc03fbb59..e26ad28b9f0e 100644
--- a/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t0.j2
+++ b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t0.j2
@@ -1,8 +1,8 @@
{% set default_cable = '5m' %}
-{% set ingress_lossless_pool_size = '8224768' %}
-{% set ingress_lossy_pool_size = '8224768' %}
-{% set egress_lossless_pool_size = '35966016' %}
-{% set egress_lossy_pool_size = '8224768' %}
+{% set ingress_lossless_pool_size = '14983147' %}
+{% set ingress_lossy_pool_size = '14983147' %}
+{% set egress_lossless_pool_size = '34340822' %}
+{% set egress_lossy_pool_size = '14983147' %}
{%- macro generate_port_lists(PORT_ALL) %}
{# Generate list of ports #}
diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t1.j2
index fe8c27b9d364..b5e4ff8d1747 100644
--- a/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t1.j2
+++ b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t1.j2
@@ -1,8 +1,8 @@
{% set default_cable = '5m' %}
-{% set ingress_lossless_pool_size = '12042240' %}
-{% set ingress_lossy_pool_size = '12042240' %}
-{% set egress_lossless_pool_size = '35966016' %}
-{% set egress_lossy_pool_size = '12042240' %}
+{% set ingress_lossless_pool_size = '9158635' %}
+{% set ingress_lossy_pool_size = '9158635' %}
+{% set egress_lossless_pool_size = '34340822' %}
+{% set egress_lossy_pool_size = '9158635' %}
{%- macro generate_port_lists(PORT_ALL) %}
{# Generate list of ports #}
diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/sai_3700.xml b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/sai_3700.xml
index 8f6c427888b1..a7ac42950668 100644
--- a/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/sai_3700.xml
+++ b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/sai_3700.xml
@@ -5,6 +5,9 @@
00:02:03:04:05:00
+
+ 1
+
32
diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/platform_components.json b/device/mellanox/x86_64-mlnx_msn3700-r0/platform_components.json
new file mode 100644
index 000000000000..7c0b7598aff7
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3700-r0/platform_components.json
@@ -0,0 +1,10 @@
+{
+ "chassis": {
+ "x86_64-mlnx_msn3700-r0": {
+ "component": {
+ "BIOS": { },
+ "CPLD": { }
+ }
+ }
+ }
+}
diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/platform_components.json b/device/mellanox/x86_64-mlnx_msn3700c-r0/platform_components.json
new file mode 100644
index 000000000000..c55b9feab7cb
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/platform_components.json
@@ -0,0 +1,10 @@
+{
+ "chassis": {
+ "x86_64-mlnx_msn3700c-r0": {
+ "component": {
+ "BIOS": { },
+ "CPLD": { }
+ }
+ }
+ }
+}
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t0.j2
deleted file mode 120000
index 85f0b6b6b354..000000000000
--- a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t0.j2
+++ /dev/null
@@ -1 +0,0 @@
-../../x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t0.j2
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t0.j2
new file mode 100644
index 000000000000..d69a0cc13835
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t0.j2
@@ -0,0 +1,104 @@
+{% set default_cable = '5m' %}
+{% set ingress_lossless_pool_size = '28196784' %}
+{% set ingress_lossy_pool_size = '28196784' %}
+{% set egress_lossless_pool_size = '34340832' %}
+{% set egress_lossy_pool_size = '28196784' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {%- for port_idx in range(0, 32) %}
+ {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %}
+ {%- endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "{{ ingress_lossless_pool_size }}",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "ingress_lossy_pool": {
+ "size": "{{ ingress_lossy_pool_size }}",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "{{ egress_lossless_pool_size }}",
+ "type": "egress",
+ "mode": "dynamic"
+ },
+ "egress_lossy_pool": {
+ "size": "{{ egress_lossy_pool_size }}",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossless_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"0"
+ },
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossy_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"7"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"4096",
+ "dynamic_th":"3"
+ },
+ "q_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
+
+{%- macro generate_profile_lists(port_names) %}
+ "BUFFER_PORT_INGRESS_PROFILE_LIST": {
+{% for port in port_names.split(',') %}
+ "{{ port }}": {
+ "profile_list" : "[BUFFER_PROFILE|ingress_lossless_profile],[BUFFER_PROFILE|ingress_lossy_profile]"
+ }{% if not loop.last %},{% endif %}
+
+{% endfor %}
+ },
+ "BUFFER_PORT_EGRESS_PROFILE_LIST": {
+{% for port in port_names.split(',') %}
+ "{{ port }}": {
+ "profile_list" : "[BUFFER_PROFILE|egress_lossless_profile],[BUFFER_PROFILE|egress_lossy_profile]"
+ }{% if not loop.last %},{% endif %}
+
+{% endfor %}
+ }
+{%- endmacro %}
+
+{%- macro generate_queue_buffers(port_names) %}
+ "BUFFER_QUEUE": {
+{% for port in port_names.split(',') %}
+ "{{ port }}|3-4": {
+ "profile" : "[BUFFER_PROFILE|egress_lossless_profile]"
+ },
+{% endfor %}
+{% for port in port_names.split(',') %}
+ "{{ port }}|0-2": {
+ "profile" : "[BUFFER_PROFILE|q_lossy_profile]"
+ },
+{% endfor %}
+{% for port in port_names.split(',') %}
+ "{{ port }}|5-6": {
+ "profile" : "[BUFFER_PROFILE|q_lossy_profile]"
+ }{% if not loop.last %},{% endif %}
+
+{% endfor %}
+ }
+{%- endmacro %}
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t1.j2
deleted file mode 120000
index 3bb496a5103b..000000000000
--- a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t1.j2
+++ /dev/null
@@ -1 +0,0 @@
-../../x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t1.j2
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t1.j2
new file mode 100644
index 000000000000..78d43455a424
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t1.j2
@@ -0,0 +1,104 @@
+{% set default_cable = '5m' %}
+{% set ingress_lossless_pool_size = '17891280' %}
+{% set ingress_lossy_pool_size = '17891280' %}
+{% set egress_lossless_pool_size = '34340832' %}
+{% set egress_lossy_pool_size = '17891280' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {%- for port_idx in range(0, 32) %}
+ {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %}
+ {%- endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "{{ ingress_lossless_pool_size }}",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "ingress_lossy_pool": {
+ "size": "{{ ingress_lossy_pool_size }}",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "{{ egress_lossless_pool_size }}",
+ "type": "egress",
+ "mode": "dynamic"
+ },
+ "egress_lossy_pool": {
+ "size": "{{ egress_lossy_pool_size }}",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossless_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"0"
+ },
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossy_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"7"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"4096",
+ "dynamic_th":"3"
+ },
+ "q_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
+
+{%- macro generate_profile_lists(port_names) %}
+ "BUFFER_PORT_INGRESS_PROFILE_LIST": {
+{% for port in port_names.split(',') %}
+ "{{ port }}": {
+ "profile_list" : "[BUFFER_PROFILE|ingress_lossless_profile],[BUFFER_PROFILE|ingress_lossy_profile]"
+ }{% if not loop.last %},{% endif %}
+
+{% endfor %}
+ },
+ "BUFFER_PORT_EGRESS_PROFILE_LIST": {
+{% for port in port_names.split(',') %}
+ "{{ port }}": {
+ "profile_list" : "[BUFFER_PROFILE|egress_lossless_profile],[BUFFER_PROFILE|egress_lossy_profile]"
+ }{% if not loop.last %},{% endif %}
+
+{% endfor %}
+ }
+{%- endmacro %}
+
+{%- macro generate_queue_buffers(port_names) %}
+ "BUFFER_QUEUE": {
+{% for port in port_names.split(',') %}
+ "{{ port }}|3-4": {
+ "profile" : "[BUFFER_PROFILE|egress_lossless_profile]"
+ },
+{% endfor %}
+{% for port in port_names.split(',') %}
+ "{{ port }}|0-2": {
+ "profile" : "[BUFFER_PROFILE|q_lossy_profile]"
+ },
+{% endfor %}
+{% for port in port_names.split(',') %}
+ "{{ port }}|5-6": {
+ "profile" : "[BUFFER_PROFILE|q_lossy_profile]"
+ }{% if not loop.last %},{% endif %}
+
+{% endfor %}
+ }
+{%- endmacro %}
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/pg_profile_lookup.ini
deleted file mode 120000
index 252ae8d4149b..000000000000
--- a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/pg_profile_lookup.ini
+++ /dev/null
@@ -1 +0,0 @@
-../../x86_64-mlnx_msn3700-r0/ACS-MSN3700/pg_profile_lookup.ini
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/pg_profile_lookup.ini
new file mode 100644
index 000000000000..7c28e4c0d500
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/pg_profile_lookup.ini
@@ -0,0 +1,23 @@
+# PG lossless profiles.
+# speed cable size xon xoff threshold
+ 1000 5m 32768 18432 14336 0
+ 10000 5m 34816 18432 16384 0
+ 25000 5m 38912 18432 20480 0
+ 40000 5m 41984 18432 23552 0
+ 50000 5m 44032 18432 25600 0
+ 100000 5m 55296 18432 36864 0
+ 200000 5m 77824 18432 59392 0
+ 1000 40m 33792 18432 15360 0
+ 10000 40m 36864 18432 18432 0
+ 25000 40m 43008 18432 24576 0
+ 40000 40m 49152 18432 30720 0
+ 50000 40m 53248 18432 34816 0
+ 100000 40m 72704 18432 54272 0
+ 200000 40m 112640 18432 94208 0
+ 1000 300m 34816 18432 16384 0
+ 10000 300m 50176 18432 31744 0
+ 25000 300m 75776 18432 57344 0
+ 40000 300m 101376 18432 82944 0
+ 50000 300m 117760 18432 99328 0
+ 100000 300m 202752 18432 184320 0
+ 200000 300m 373760 18432 355328 0
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/sai_3800.xml b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/sai_3800.xml
index 2d4c0f93d100..1b3c77ce381c 100644
--- a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/sai_3800.xml
+++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/sai_3800.xml
@@ -5,6 +5,9 @@
00:02:03:04:05:00
+
+ 1
+
64
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/buffers.json.j2
new file mode 120000
index 000000000000..add8bf8bb7c2
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/buffers.json.j2
@@ -0,0 +1 @@
+../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers.json.j2
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/buffers_defaults_t0.j2
new file mode 120000
index 000000000000..0987f6724863
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/buffers_defaults_t0.j2
@@ -0,0 +1 @@
+../ACS-MSN3800/buffers_defaults_t0.j2
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/buffers_defaults_t1.j2
new file mode 120000
index 000000000000..119460bfa556
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/buffers_defaults_t1.j2
@@ -0,0 +1 @@
+../ACS-MSN3800/buffers_defaults_t1.j2
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/pg_profile_lookup.ini
new file mode 120000
index 000000000000..db2f74508aad
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/pg_profile_lookup.ini
@@ -0,0 +1 @@
+../ACS-MSN3800/pg_profile_lookup.ini
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/port_config.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/port_config.ini
new file mode 100644
index 000000000000..9559119c7e38
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/port_config.ini
@@ -0,0 +1,105 @@
+# name lanes alias index speed fec
+Ethernet0 0,1 etp1a 0 50000 none
+Ethernet2 2,3 etp1b 0 50000 none
+Ethernet4 4,5 etp2a 1 50000 none
+Ethernet6 6,7 etp2b 1 50000 none
+Ethernet8 8,9 etp3a 2 50000 none
+Ethernet10 10,11 etp3b 2 50000 none
+Ethernet12 12,13,14,15 etp4 3 50000 none
+Ethernet16 16,17 etp5a 4 50000 none
+Ethernet18 18,19 etp5b 4 50000 none
+Ethernet20 20,21 etp6a 5 50000 none
+Ethernet22 22,23 etp6b 5 50000 none
+Ethernet24 24,25 etp7a 6 50000 none
+Ethernet26 26,27 etp7b 6 50000 none
+Ethernet28 28,29,30,31 etp8 7 50000 none
+Ethernet32 32,33 etp9a 8 50000 none
+Ethernet34 34,35 etp9b 8 50000 none
+Ethernet36 36,37 etp10a 9 50000 none
+Ethernet38 38,39 etp10b 9 50000 none
+Ethernet40 40,41 etp11a 10 50000 none
+Ethernet42 42,43 etp11b 10 50000 none
+Ethernet44 44,45,46,47 etp12 11 50000 none
+Ethernet48 48,49 etp13a 12 50000 none
+Ethernet50 50,51 etp13b 12 50000 none
+Ethernet52 52,53 etp14a 13 50000 none
+Ethernet54 54,55 etp14b 13 50000 none
+Ethernet56 56,57 etp15a 14 50000 none
+Ethernet58 58,59 etp15b 14 50000 none
+Ethernet60 60,61,62,63 etp16 15 50000 none
+Ethernet64 64,65 etp17a 16 50000 none
+Ethernet66 66,67 etp17b 16 50000 none
+Ethernet68 68,69 etp18a 17 50000 none
+Ethernet70 70,71 etp18b 17 50000 none
+Ethernet72 72,73 etp19a 18 50000 none
+Ethernet74 74,75 etp19b 18 50000 none
+Ethernet76 76,77,78,79 etp20 19 50000 none
+Ethernet80 80,81 etp21a 20 50000 none
+Ethernet82 82,83 etp21b 20 50000 none
+Ethernet84 84,85 etp22a 21 50000 none
+Ethernet86 86,87 etp22b 21 50000 none
+Ethernet88 88,89 etp23a 22 50000 none
+Ethernet90 90,91 etp23b 22 50000 none
+Ethernet92 92,93,94,95 etp24 23 50000 none
+Ethernet96 96,97,98,99 etp25 24 100000 rs
+Ethernet100 100,101,102,103 etp26 25 100000 rs
+Ethernet104 104,105 etp27a 26 50000 none
+Ethernet106 106,107 etp27b 26 50000 none
+Ethernet108 108,109,110,111 etp28 27 50000 none
+Ethernet112 112,113,114,115 etp29 28 100000 rs
+Ethernet116 116,117,118,119 etp30 29 100000 rs
+Ethernet120 120,121 etp31a 30 50000 none
+Ethernet122 122,123 etp31b 30 50000 none
+Ethernet124 124,125,126,127 etp32 31 50000 none
+Ethernet128 128,129,130,131 etp33 32 100000 rs
+Ethernet132 132,133,134,135 etp34 33 100000 rs
+Ethernet136 136,137 etp35a 34 50000 none
+Ethernet138 138,139 etp35b 34 50000 none
+Ethernet140 140,141,142,143 etp36 35 50000 none
+Ethernet144 144,145,146,147 etp37 36 100000 rs
+Ethernet148 148,149,150,151 etp38 37 100000 rs
+Ethernet152 152,153 etp39a 38 50000 none
+Ethernet154 154,155 etp39b 38 50000 none
+Ethernet156 156,157,158,159 etp40 39 50000 none
+Ethernet160 160,161 etp41a 40 50000 none
+Ethernet162 162,163 etp41b 40 50000 none
+Ethernet164 164,165 etp42a 41 50000 none
+Ethernet166 166,167 etp42b 41 50000 none
+Ethernet168 168,169 etp43a 42 50000 none
+Ethernet170 170,171 etp43b 42 50000 none
+Ethernet172 172,173,174,175 etp44 43 50000 none
+Ethernet176 176,177 etp45a 44 50000 none
+Ethernet178 178,179 etp45b 44 50000 none
+Ethernet180 180,181 etp46a 45 50000 none
+Ethernet182 182,183 etp46b 45 50000 none
+Ethernet184 184,185 etp47a 46 50000 none
+Ethernet186 186,187 etp47b 46 50000 none
+Ethernet188 188,189,190,191 etp48 47 50000 none
+Ethernet192 192,193 etp49a 48 50000 none
+Ethernet194 194,195 etp49b 48 50000 none
+Ethernet196 196,197 etp50a 49 50000 none
+Ethernet198 198,199 etp50b 49 50000 none
+Ethernet200 200,201 etp51a 50 50000 none
+Ethernet202 202,203 etp51b 50 50000 none
+Ethernet204 204,205,206,207 etp52 51 50000 none
+Ethernet208 208,209 etp53a 52 50000 none
+Ethernet210 210,211 etp53b 52 50000 none
+Ethernet212 212,213 etp54a 53 50000 none
+Ethernet214 214,215 etp54b 53 50000 none
+Ethernet216 216,217 etp55a 54 50000 none
+Ethernet218 218,219 etp55b 54 50000 none
+Ethernet220 220,221,222,223 etp56 55 50000 none
+Ethernet224 224,225 etp57a 56 50000 none
+Ethernet226 226,227 etp57b 56 50000 none
+Ethernet228 228,229 etp58a 57 50000 none
+Ethernet230 230,231 etp58b 57 50000 none
+Ethernet232 232,233 etp59a 58 50000 none
+Ethernet234 234,235 etp59b 58 50000 none
+Ethernet236 236,237,238,239 etp60 59 50000 none
+Ethernet240 240,241 etp61a 60 50000 none
+Ethernet242 242,243 etp61b 60 50000 none
+Ethernet244 244,245 etp62a 61 50000 none
+Ethernet246 246,247 etp62b 61 50000 none
+Ethernet248 248,249 etp63a 62 50000 none
+Ethernet250 250,251 etp63b 62 50000 none
+Ethernet252 252,253,254,255 etp64 63 50000 none
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/qos.json.j2
new file mode 120000
index 000000000000..eccf286dc879
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/qos.json.j2
@@ -0,0 +1 @@
+../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/qos.json.j2
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/sai.profile b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/sai.profile
new file mode 100644
index 000000000000..c5bb0c90f3d7
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/sai.profile
@@ -0,0 +1 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_3800_112x50g_8x100g.xml
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/sai_3800_112x50g_8x100g.xml b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/sai_3800_112x50g_8x100g.xml
new file mode 100644
index 000000000000..102842d72275
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/sai_3800_112x50g_8x100g.xml
@@ -0,0 +1,507 @@
+
+
+
+
+
+ 00:02:03:04:05:00
+
+
+ 64
+
+
+
+
+ 1
+ 4
+ 48
+
+
+ 3
+ 2
+
+
+ 384
+
+
+ 3
+ 4
+ 49
+ 3
+ 2
+ 384
+
+
+ 5
+ 4
+ 50
+ 3
+ 2
+ 384
+
+
+ 7
+ 4
+ 51
+ 3
+ 384
+
+
+ 9
+ 4
+ 52
+ 3
+ 2
+ 384
+
+
+ 11
+ 4
+ 53
+ 3
+ 2
+ 384
+
+
+ 13
+ 4
+ 54
+ 3
+ 2
+ 384
+
+
+ 15
+ 4
+ 55
+ 3
+ 384
+
+
+ 17
+ 4
+ 56
+ 3
+ 2
+ 384
+
+
+ 19
+ 4
+ 57
+ 3
+ 2
+ 384
+
+
+ 21
+ 4
+ 58
+ 3
+ 2
+ 384
+
+
+ 23
+ 4
+ 59
+ 3
+ 384
+
+
+ 25
+ 4
+ 60
+ 3
+ 2
+ 384
+
+
+ 27
+ 4
+ 61
+ 3
+ 2
+ 384
+
+
+ 29
+ 4
+ 62
+ 3
+ 2
+ 384
+
+
+ 31
+ 4
+ 63
+ 3
+ 384
+
+
+ 33
+ 4
+ 12
+ 3
+ 2
+ 384
+
+
+ 35
+ 4
+ 13
+ 3
+ 2
+ 384
+
+
+ 37
+ 4
+ 14
+ 3
+ 2
+ 384
+
+
+ 39
+ 4
+ 15
+ 3
+ 384
+
+
+ 41
+ 4
+ 8
+ 3
+ 2
+ 384
+
+
+ 43
+ 4
+ 9
+ 3
+ 2
+ 384
+
+
+ 45
+ 4
+ 10
+ 3
+ 2
+ 384
+
+
+ 47
+ 4
+ 11
+ 3
+ 384
+
+
+ 49
+ 4
+ 4
+ 3
+ 2
+ 384
+
+
+ 51
+ 4
+ 5
+ 3
+ 2
+ 384
+
+
+ 53
+ 4
+ 6
+ 3
+ 2
+ 384
+
+
+ 55
+ 4
+ 7
+ 3
+ 384
+
+
+ 57
+ 4
+ 0
+ 3
+ 2
+ 384
+
+
+ 59
+ 4
+ 1
+ 3
+ 2
+ 384
+
+
+ 61
+ 4
+ 2
+ 3
+ 2
+ 384
+
+
+ 63
+ 4
+ 3
+ 3
+ 384
+
+
+ 65
+ 4
+ 44
+ 3
+ 2
+ 384
+
+
+ 67
+ 4
+ 45
+ 3
+ 2
+ 384
+
+
+ 69
+ 4
+ 46
+ 3
+ 2
+ 384
+
+
+ 71
+ 4
+ 47
+ 3
+ 384
+
+
+ 73
+ 4
+ 40
+ 3
+ 2
+ 384
+
+
+ 75
+ 4
+ 41
+ 3
+ 2
+ 384
+
+
+ 77
+ 4
+ 42
+ 3
+ 2
+ 384
+
+
+ 79
+ 4
+ 43
+ 3
+ 384
+
+
+ 81
+ 4
+ 36
+ 3
+ 1536
+
+
+ 83
+ 4
+ 37
+ 3
+ 1536
+
+
+ 85
+ 4
+ 38
+ 3
+ 2
+ 384
+
+
+ 87
+ 4
+ 39
+ 3
+ 384
+
+
+ 89
+ 4
+ 32
+ 3
+ 1536
+
+
+ 91
+ 4
+ 33
+ 3
+ 1536
+
+
+ 93
+ 4
+ 34
+ 3
+ 2
+ 384
+
+
+ 95
+ 4
+ 35
+ 3
+ 384
+
+
+ 97
+ 4
+ 16
+ 3
+ 2
+ 384
+
+
+ 99
+ 4
+ 17
+ 3
+ 2
+ 384
+
+
+ 101
+ 4
+ 18
+ 3
+ 2
+ 384
+
+
+ 103
+ 4
+ 19
+ 3
+ 384
+
+
+ 105
+ 4
+ 20
+ 3
+ 2
+ 384
+
+
+ 107
+ 4
+ 21
+ 3
+ 2
+ 384
+
+
+ 109
+ 4
+ 22
+ 3
+ 2
+ 384
+
+
+ 111
+ 4
+ 23
+ 3
+ 384
+
+
+ 113
+ 4
+ 24
+ 3
+ 1536
+
+
+ 115
+ 4
+ 25
+ 3
+ 1536
+
+
+ 117
+ 4
+ 26
+ 3
+ 2
+ 384
+
+
+ 119
+ 4
+ 27
+ 3
+ 384
+
+
+ 121
+ 4
+ 28
+ 3
+ 1536
+
+
+ 123
+ 4
+ 29
+ 3
+ 1536
+
+
+ 125
+ 4
+ 30
+ 3
+ 2
+ 384
+
+
+ 127
+ 4
+ 31
+ 3
+ 384
+
+
+
+
diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/platform_components.json b/device/mellanox/x86_64-mlnx_msn3800-r0/platform_components.json
new file mode 100644
index 000000000000..fa3b172b763e
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn3800-r0/platform_components.json
@@ -0,0 +1,10 @@
+{
+ "chassis": {
+ "x86_64-mlnx_msn3800-r0": {
+ "component": {
+ "BIOS": { },
+ "CPLD": { }
+ }
+ }
+ }
+}
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers.json.j2
new file mode 120000
index 000000000000..add8bf8bb7c2
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers.json.j2
@@ -0,0 +1 @@
+../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers.json.j2
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_defaults_t0.j2
new file mode 100644
index 000000000000..b71e6b35fa2e
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_defaults_t0.j2
@@ -0,0 +1,106 @@
+{% set default_cable = '5m' %}
+{% set ingress_lossless_pool_size = '56623104' %}
+{% set ingress_lossy_pool_size = '56623104' %}
+{% set egress_lossless_pool_size = '60817392' %}
+{% set egress_lossy_pool_size = '56623104' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {%- for port_idx in range(0, 32) %}
+ {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %}
+ {%- endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "{{ ingress_lossless_pool_size }}",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "ingress_lossy_pool": {
+ "size": "{{ ingress_lossy_pool_size }}",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "{{ egress_lossless_pool_size }}",
+ "type": "egress",
+ "mode": "dynamic"
+ },
+ "egress_lossy_pool": {
+ "size": "{{ egress_lossy_pool_size }}",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossless_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"0"
+ },
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossy_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"7"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"4096",
+ "dynamic_th":"3"
+ },
+ "q_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
+
+{%- macro generate_profile_lists(port_names) %}
+ "BUFFER_PORT_INGRESS_PROFILE_LIST": {
+{% for port in port_names.split(',') %}
+ "{{ port }}": {
+ "profile_list" : "[BUFFER_PROFILE|ingress_lossless_profile],[BUFFER_PROFILE|ingress_lossy_profile]"
+ }{% if not loop.last %},{% endif %}
+
+{% endfor %}
+ },
+ "BUFFER_PORT_EGRESS_PROFILE_LIST": {
+{% for port in port_names.split(',') %}
+ "{{ port }}": {
+ "profile_list" : "[BUFFER_PROFILE|egress_lossless_profile],[BUFFER_PROFILE|egress_lossy_profile]"
+ }{% if not loop.last %},{% endif %}
+
+{% endfor %}
+ }
+{%- endmacro %}
+
+{%- macro generate_queue_buffers(port_names) %}
+ "BUFFER_QUEUE": {
+{% for port in port_names.split(',') %}
+ "{{ port }}|3-4": {
+ "profile" : "[BUFFER_PROFILE|egress_lossless_profile]"
+ },
+{% endfor %}
+{% for port in port_names.split(',') %}
+ "{{ port }}|0-2": {
+ "profile" : "[BUFFER_PROFILE|q_lossy_profile]"
+ },
+{% endfor %}
+{% for port in port_names.split(',') %}
+ "{{ port }}|5-6": {
+ "profile" : "[BUFFER_PROFILE|q_lossy_profile]"
+ }{% if not loop.last %},{% endif %}
+
+{% endfor %}
+ }
+{%- endmacro %}
+
+
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_defaults_t1.j2
new file mode 100644
index 000000000000..87e55d5a46e0
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_defaults_t1.j2
@@ -0,0 +1,106 @@
+{% set default_cable = '5m' %}
+{% set ingress_lossless_pool_size = '36011952' %}
+{% set ingress_lossy_pool_size = '36011952' %}
+{% set egress_lossless_pool_size = '60817392' %}
+{% set egress_lossy_pool_size = '36011952' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {%- for port_idx in range(0, 32) %}
+ {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %}
+ {%- endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "{{ ingress_lossless_pool_size }}",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "ingress_lossy_pool": {
+ "size": "{{ ingress_lossy_pool_size }}",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "{{ egress_lossless_pool_size }}",
+ "type": "egress",
+ "mode": "dynamic"
+ },
+ "egress_lossy_pool": {
+ "size": "{{ egress_lossy_pool_size }}",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossless_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"0"
+ },
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossy_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"7"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"4096",
+ "dynamic_th":"3"
+ },
+ "q_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
+
+{%- macro generate_profile_lists(port_names) %}
+ "BUFFER_PORT_INGRESS_PROFILE_LIST": {
+{% for port in port_names.split(',') %}
+ "{{ port }}": {
+ "profile_list" : "[BUFFER_PROFILE|ingress_lossless_profile],[BUFFER_PROFILE|ingress_lossy_profile]"
+ }{% if not loop.last %},{% endif %}
+
+{% endfor %}
+ },
+ "BUFFER_PORT_EGRESS_PROFILE_LIST": {
+{% for port in port_names.split(',') %}
+ "{{ port }}": {
+ "profile_list" : "[BUFFER_PROFILE|egress_lossless_profile],[BUFFER_PROFILE|egress_lossy_profile]"
+ }{% if not loop.last %},{% endif %}
+
+{% endfor %}
+ }
+{%- endmacro %}
+
+{%- macro generate_queue_buffers(port_names) %}
+ "BUFFER_QUEUE": {
+{% for port in port_names.split(',') %}
+ "{{ port }}|3-4": {
+ "profile" : "[BUFFER_PROFILE|egress_lossless_profile]"
+ },
+{% endfor %}
+{% for port in port_names.split(',') %}
+ "{{ port }}|0-2": {
+ "profile" : "[BUFFER_PROFILE|q_lossy_profile]"
+ },
+{% endfor %}
+{% for port in port_names.split(',') %}
+ "{{ port }}|5-6": {
+ "profile" : "[BUFFER_PROFILE|q_lossy_profile]"
+ }{% if not loop.last %},{% endif %}
+
+{% endfor %}
+ }
+{%- endmacro %}
+
+
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/pg_profile_lookup.ini
new file mode 100644
index 000000000000..950cf9434967
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/pg_profile_lookup.ini
@@ -0,0 +1,25 @@
+# speed cable size xon xoff threshold
+1000 5m 32768 18432 14336 0
+10000 5m 32768 18432 14336 0
+25000 5m 33792 18432 15360 0
+40000 5m 33792 18432 15360 0
+50000 5m 33792 18432 15360 0
+100000 5m 35840 18432 17408 0
+200000 5m 37888 18432 19456 0
+400000 5m 43008 18432 24576 0
+1000 40m 32768 18432 14336 0
+10000 40m 34816 18432 16384 0
+25000 40m 37888 18432 19456 0
+40000 40m 40960 18432 22528 0
+50000 40m 43008 18432 24576 0
+100000 40m 53248 18432 34816 0
+200000 40m 72704 18432 54272 0
+400000 40m 112640 18432 94208 0
+1000 300m 34816 18432 16384 0
+10000 300m 48128 18432 29696 0
+25000 300m 70656 18432 52224 0
+40000 300m 93184 18432 74752 0
+50000 300m 108544 18432 90112 0
+100000 300m 183296 18432 164864 0
+200000 300m 333824 18432 315392 0
+400000 300m 634880 18432 616448 0
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/port_config.ini b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/port_config.ini
new file mode 100644
index 000000000000..1e1906ff0ef5
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/port_config.ini
@@ -0,0 +1,33 @@
+# name lanes alias
+Ethernet0 0,1,2,3 etp1
+Ethernet4 4,5,6,7 etp2
+Ethernet8 8,9,10,11 etp3
+Ethernet12 12,13,14,15 etp4
+Ethernet16 16,17,18,19 etp5
+Ethernet20 20,21,22,23 etp6
+Ethernet24 24,25,26,27 etp7
+Ethernet28 28,29,30,31 etp8
+Ethernet32 32,33,34,35 etp9
+Ethernet36 36,37,38,39 etp10
+Ethernet40 40,41,42,43 etp11
+Ethernet44 44,45,46,47 etp12
+Ethernet48 48,49,50,51 etp13
+Ethernet52 52,53,54,55 etp14
+Ethernet56 56,57,58,59 etp15
+Ethernet60 60,61,62,63 etp16
+Ethernet64 64,65,66,67 etp17
+Ethernet68 68,69,70,71 etp18
+Ethernet72 72,73,74,75 etp19
+Ethernet76 76,77,78,79 etp20
+Ethernet80 80,81,82,83 etp21
+Ethernet84 84,85,86,87 etp22
+Ethernet88 88,89,90,91 etp23
+Ethernet92 92,93,94,95 etp24
+Ethernet96 96,97,98,99 etp25
+Ethernet100 100,101,102,103 etp26
+Ethernet104 104,105,106,107 etp27
+Ethernet108 108,109,110,111 etp28
+Ethernet112 112,113,114,115 etp29
+Ethernet116 116,117,118,119 etp30
+Ethernet120 120,121,122,123 etp31
+Ethernet124 124,125,126,127 etp32
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/qos.json.j2
new file mode 120000
index 000000000000..eccf286dc879
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/qos.json.j2
@@ -0,0 +1 @@
+../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/qos.json.j2
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/sai.profile b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/sai.profile
new file mode 100644
index 000000000000..31b3fd09ddd9
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/sai.profile
@@ -0,0 +1 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_4700_100G.xml
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/sai_4700_100G.xml b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/sai_4700_100G.xml
new file mode 100644
index 000000000000..a76e23d5d119
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/sai_4700_100G.xml
@@ -0,0 +1,244 @@
+
+
+
+
+
+ 00:02:03:04:05:00
+
+
+ 32
+
+
+
+
+ 1
+ 4
+ 17
+ 3
+ 1536
+
+
+ 5
+ 4
+ 16
+ 3
+ 1536
+
+
+ 9
+ 4
+ 19
+ 3
+ 1536
+
+
+ 13
+ 4
+ 18
+ 3
+ 1536
+
+
+ 17
+ 4
+ 21
+ 3
+ 1536
+
+
+ 21
+ 4
+ 20
+ 3
+ 1536
+
+
+ 25
+ 4
+ 23
+ 3
+ 1536
+
+
+ 29
+ 4
+ 22
+ 3
+ 1536
+
+
+ 33
+ 4
+ 29
+ 3
+ 1536
+
+
+ 37
+ 4
+ 28
+ 3
+ 1536
+
+
+ 41
+ 4
+ 31
+ 3
+ 1536
+
+
+ 45
+ 4
+ 30
+ 3
+ 1536
+
+
+ 49
+ 4
+ 25
+ 3
+ 1536
+
+
+ 53
+ 4
+ 24
+ 3
+ 1536
+
+
+ 57
+ 4
+ 27
+ 3
+ 1536
+
+
+ 61
+ 4
+ 26
+ 3
+ 1536
+
+
+ 65
+ 4
+ 14
+ 3
+ 1536
+
+
+ 69
+ 4
+ 15
+ 3
+ 1536
+
+
+ 73
+ 4
+ 12
+ 3
+ 1536
+
+
+ 77
+ 4
+ 13
+ 3
+ 1536
+
+
+ 81
+ 4
+ 10
+ 3
+ 1536
+
+
+ 85
+ 4
+ 11
+ 3
+ 1536
+
+
+ 89
+ 4
+ 8
+ 3
+ 1536
+
+
+ 93
+ 4
+ 9
+ 3
+ 1536
+
+
+ 97
+ 4
+ 2
+ 3
+ 1536
+
+
+ 101
+ 4
+ 3
+ 3
+ 1536
+
+
+ 105
+ 4
+ 0
+
+
+ 3
+
+
+ 1536
+
+
+ 109
+ 4
+ 1
+ 3
+ 1536
+
+
+ 113
+ 4
+ 6
+ 3
+ 1536
+
+
+ 117
+ 4
+ 7
+ 3
+ 1536
+
+
+ 121
+ 4
+ 4
+ 3
+ 1536
+
+
+ 125
+ 4
+ 5
+ 3
+ 1536
+
+
+
+
+
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/default_sku b/device/mellanox/x86_64-mlnx_msn4700-r0/default_sku
new file mode 100644
index 000000000000..80e541477f79
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/default_sku
@@ -0,0 +1 @@
+ACS-MSN4700 t1
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/platform_components.json b/device/mellanox/x86_64-mlnx_msn4700-r0/platform_components.json
new file mode 100644
index 000000000000..2804e29e11b1
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/platform_components.json
@@ -0,0 +1,10 @@
+{
+ "chassis": {
+ "x86_64-mlnx_msn4700-r0": {
+ "component": {
+ "BIOS": { },
+ "CPLD": { }
+ }
+ }
+ }
+}
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn4700-r0/platform_reboot
new file mode 120000
index 000000000000..43c8ea567493
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/platform_reboot
@@ -0,0 +1 @@
+../x86_64-mlnx_msn2700-r0/platform_reboot
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/platform_wait b/device/mellanox/x86_64-mlnx_msn4700-r0/platform_wait
new file mode 120000
index 000000000000..4b30bd429854
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/platform_wait
@@ -0,0 +1 @@
+../x86_64-mlnx_msn2700-r0/platform_wait
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/eeprom.py
new file mode 120000
index 000000000000..b4e2a6a61671
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/eeprom.py
@@ -0,0 +1 @@
+../../x86_64-mlnx_msn2700-r0/plugins/eeprom.py
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/psuutil.py
new file mode 120000
index 000000000000..9f724238a8d5
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/psuutil.py
@@ -0,0 +1 @@
+../../x86_64-mlnx_msn2700-r0/plugins/psuutil.py
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/sfplpmget.py
new file mode 120000
index 000000000000..2e84f435abd9
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/sfplpmget.py
@@ -0,0 +1 @@
+../../x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/sfplpmset.py
new file mode 120000
index 000000000000..6a88bac30467
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/sfplpmset.py
@@ -0,0 +1 @@
+../../x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/sfpreset.py
new file mode 120000
index 000000000000..fef2063e3496
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/sfpreset.py
@@ -0,0 +1 @@
+../../x86_64-mlnx_msn2700-r0/plugins/sfpreset.py
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/sfputil.py
new file mode 120000
index 000000000000..45909b880fc9
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/plugins/sfputil.py
@@ -0,0 +1 @@
+../../x86_64-mlnx_msn2700-r0/plugins/sfputil.py
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn4700-r0/pmon_daemon_control.json
new file mode 120000
index 000000000000..435a2ce7c0ba
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/pmon_daemon_control.json
@@ -0,0 +1 @@
+../x86_64-mlnx_msn2700-r0/pmon_daemon_control.json
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn4700-r0/sensors.conf
new file mode 100644
index 000000000000..b4eaf76f2ec0
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700-r0/sensors.conf
@@ -0,0 +1,162 @@
+################################################################################
+# Copyright (c) 2019 Mellanox Technologies
+#
+# Platform specific sensors config for SN4700
+################################################################################
+
+# Temperature sensors
+bus "i2c-2" "i2c-1-mux (chan_id 1)"
+ chip "mlxsw-i2c-*-48"
+ label temp1 "Ambient ASIC Temp"
+
+bus "i2c-7" "i2c-1-mux (chan_id 6)"
+ chip "tmp102-i2c-*-49"
+ label temp1 "Ambient Fan Side Temp (air intake)"
+ chip "tmp102-i2c-*-4a"
+ label temp1 "Ambient Port Side Temp (air exhaust)"
+
+bus "i2c-15" "i2c-1-mux (chan_id 6)"
+ chip "tmp102-i2c-15-49"
+ label temp1 "Ambient COMEX Temp"
+
+# Power controllers
+bus "i2c-5" "i2c-1-mux (chan_id 4)"
+ chip "tps53679-i2c-*-62"
+ label in1 "PMIC-1 PSU 12V Rail (in)"
+ label in2 "PMIC-1 ASIC 0.8V VCORE_MAIN Rail (out)"
+ ignore in3
+ label temp1 "PMIC-1 Temp 1"
+ label temp2 "PMIC-1 Temp 2"
+ label power1 "PMIC-1 ASIC 0.8V VCORE_MAIN Rail Pwr (out)"
+ ignore power2
+ label curr1 "PMIC-1 ASIC 0.8V VCORE_MAIN Rail Curr (out)"
+ ignore curr2
+ chip "tps53679-i2c-*-64"
+ label in1 "PMIC-2 PSU 12V Rail (in)"
+ label in2 "PMIC-2 ASIC 1.8V MAIN Rail (out)"
+ compute in2 (1.5)*@, @/(1.5)
+ label in3 "PMIC-2 ASIC 1.2V MAIN Rail (out)"
+ label temp1 "PMIC-2 Temp 1"
+ label temp2 "PMIC-2 Temp 2"
+ label power1 "PMIC-2 ASIC 1.8V MAIN Rail Pwr (out)"
+ label power2 "PMIC-2 ASIC 1.2V MAIN Rail Pwr (out)"
+ label curr1 "PMIC-2 ASIC 1.8V MAIN Rail Curr (out)"
+ label curr2 "PMIC-2 ASIC 1.2V MAIN Rail Curr (out)"
+ chip "tps53679-i2c-*-66"
+ label in1 "PMIC-3 PSU 12V Rail (in)"
+ label in2 "PMIC-3 ASIC 0.85V VCORE_T0_1 Rail (out)"
+ label in3 "PMIC-3 ASIC 1.8V T0_1 Rail (out)"
+ label temp1 "PMIC-3 Temp 1"
+ label temp2 "PMIC-3 Temp 2"
+ label power1 "PMIC-3 ASIC 0.85V VCORE_T0_1 Rail Pwr (out)"
+ label power2 "PMIC-3 ASIC 1.8V T0_1 Rail Pwr (out)"
+ label curr1 "PMIC-3 ASIC 0.85V VCORE_T0_1 Rail Curr (out)"
+ label curr2 "PMIC-3 ASIC 1.8V T0_1 Rail Curr (out)"
+ chip "tps53679-i2c-*-68"
+ label in1 "PMIC-4 PSU 12V Rail (in)"
+ label in2 "PMIC-4 ASIC 0.85V VCORE_T2_3 Rail (out)"
+ label in3 "PMIC-4 ASIC 1.8V T2_3 Rail (out)"
+ label temp1 "PMIC-4 Temp 1"
+ label temp2 "PMIC-4 Temp 2"
+ label power1 "PMIC-4 ASIC 0.85V VCORE_T2_3 Rail Pwr (out)"
+ label power2 "PMIC-4 ASIC 1.8V T2_3 Rail Pwr (out)"
+ label curr1 "PMIC-4 ASIC 0.85V VCORE_T2_3 Rail Curr (out)"
+ label curr2 "PMIC-4 ASIC 1.8V T2_3 Rail Curr (out)"
+ chip "tps53679-i2c-*-6a"
+ label in1 "PMIC-5 PSU 12V Rail (in)"
+ label in2 "PMIC-5 ASIC 0.85V VCORE_T4_5 Rail (out)"
+ label in3 "PMIC-5 ASIC 1.8V T4_5 Rail (out)"
+ label temp1 "PMIC-5 Temp 1"
+ label temp2 "PMIC-5 Temp 2"
+ label power1 "PMIC-5 ASIC 0.85V VCORE_T4_5 Rail Pwr (out)"
+ label power2 "PMIC-5 ASIC 1.8V T4_5 Rail Pwr (out)"
+ label curr1 "PMIC-5 ASIC 0.85V VCORE_T4_5 Rail Curr (out)"
+ label curr2 "PMIC-5 ASIC 1.8V T4_5 Rail Curr (out)"
+ chip "tps53679-i2c-*-6c"
+ label in1 "PMIC-6 PSU 12V Rail (in)"
+ label in2 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail (out)"
+ label in3 "PMIC-6 ASIC 1.8V T6_7 Rail (out)"
+ label temp1 "PMIC-6 Temp 1"
+ label temp2 "PMIC-6 Temp 2"
+ label power1 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail Pwr (out)"
+ label power2 "PMIC-6 ASIC 1.8V T6_7 Rail Pwr (out)"
+ label curr1 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail Curr (out)"
+ label curr2 "PMIC-6 ASIC 1.8V T6_7 Rail Curr (out)"
+ chip "tps53679-i2c-*-6e"
+ label in1 "PMIC-7 PSU 12V Rail (in)"
+ label in2 "PMIC-7 ASIC 1.2V T0_3 Rail (out)"
+ label in3 "PMIC-7 ASIC 1.2V T4_7 Rail (out)"
+ label temp1 "PMIC-7 Temp 1"
+ label temp2 "PMIC-7 Temp 2"
+ label power1 "PMIC-7 ASIC 1.2V T0_3 Rail Pwr (out)"
+ label power2 "PMIC-7 ASIC 1.2V T4_7 Rail Pwr (out)"
+ label curr1 "PMIC-7 ASIC 1.2V T0_3 Rail Curr (out)"
+ label curr2 "PMIC-7 ASIC 1.2V T4_7 Rail Curr (out)"
+
+bus "i2c-15" "i2c-1-mux (chan_id 6)"
+ chip "tps53679-i2c-*-58"
+ label in1 "PMIC-8 PSU 12V Rail (in)"
+ label in2 "PMIC-8 COMEX 1.8V Rail (out)"
+ label in3 "PMIC-8 COMEX 1.05V Rail (out)"
+ label temp1 "PMIC-8 Temp 1"
+ label temp2 "PMIC-8 Temp 2"
+ label power1 "PMIC-8 COMEX 1.8V Rail Pwr (out)"
+ label power2 "PMIC-8 COMEX 1.05V Rail Pwr (out)"
+ label curr1 "PMIC-8 COMEX 1.8V Rail Curr (out)"
+ label curr2 "PMIC-8 COMEX 1.05V Rail Curr (out)"
+ chip "tps53679-i2c-*-61"
+ label in1 "PMIC-9 PSU 12V Rail (in)"
+ label in2 "PMIC-9 COMEX 1.2V Rail (out)"
+ ignore in3
+ label temp1 "PMIC-9 Temp 1"
+ label temp2 "PMIC-9 Temp 2"
+ label power1 "PMIC-9 COMEX 1.2V Rail Pwr (out)"
+ ignore power2
+ label curr1 "PMIC-9 COMEX 1.2V Rail Curr (out)"
+ ignore curr2
+
+# Power supplies
+bus "i2c-4" "i2c-1-mux (chan_id 3)"
+ chip "dps460-i2c-*-58"
+ label in1 "PSU-1(L) 220V Rail (in)"
+ ignore in2
+ label in3 "PSU-1(L) 12V Rail (out)"
+ label fan1 "PSU-1(L) Fan 1"
+ label temp1 "PSU-1(L) Temp 1"
+ label temp2 "PSU-1(L) Temp 2"
+ label temp3 "PSU-1(L) Temp 3"
+ label power1 "PSU-1(L) 220V Rail Pwr (in)"
+ label power2 "PSU-1(L) 12V Rail Pwr (out)"
+ label curr1 "PSU-1(L) 220V Rail Curr (in)"
+ label curr2 "PSU-1(L) 12V Rail Curr (out)"
+ chip "dps460-i2c-*-59"
+ label in1 "PSU-2(R) 220V Rail (in)"
+ ignore in2
+ label in3 "PSU-2(R) 12V Rail (out)"
+ label fan1 "PSU-2(R) Fan 1"
+ label temp1 "PSU-2(R) Temp 1"
+ label temp2 "PSU-2(R) Temp 2"
+ label temp3 "PSU-2(R) Temp 3"
+ label power1 "PSU-2(R) 220V Rail Pwr (in)"
+ label power2 "PSU-2(R) 12V Rail Pwr (out)"
+ label curr1 "PSU-2(R) 220V Rail Curr (in)"
+ label curr2 "PSU-2(R) 12V Rail Curr (out)"
+
+# Chassis fans
+chip "mlxreg_fan-isa-*"
+ label fan1 "Chassis Fan Drawer-1 Tach 1"
+ label fan2 "Chassis Fan Drawer-1 Tach 2"
+ label fan3 "Chassis Fan Drawer-2 Tach 1"
+ label fan4 "Chassis Fan Drawer-2 Tach 2"
+ label fan5 "Chassis Fan Drawer-3 Tach 1"
+ label fan6 "Chassis Fan Drawer-3 Tach 2"
+ label fan7 "Chassis Fan Drawer-4 Tach 1"
+ label fan8 "Chassis Fan Drawer-4 Tach 2"
+ label fan9 "Chassis Fan Drawer-5 Tach 1"
+ label fan10 "Chassis Fan Drawer-5 Tach 2"
+ label fan11 "Chassis Fan Drawer-6 Tach 1"
+ label fan12 "Chassis Fan Drawer-6 Tach 2"
+
+# Miscellaneous
+chip "*-virtual-*"
+ ignore temp1
diff --git a/device/mellanox/x86_64-mlnx_msn4700_simx-r0/ACS-MSN4700 b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/ACS-MSN4700
new file mode 120000
index 000000000000..3f61c9909a65
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/ACS-MSN4700
@@ -0,0 +1 @@
+../x86_64-mlnx_msn4700-r0/ACS-MSN4700
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700_simx-r0/default_sku b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/default_sku
new file mode 120000
index 000000000000..6f72f84de680
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/default_sku
@@ -0,0 +1 @@
+../x86_64-mlnx_msn4700-r0/default_sku
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700_simx-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/platform_reboot
new file mode 120000
index 000000000000..dfaf53417665
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/platform_reboot
@@ -0,0 +1 @@
+../x86_64-mlnx_msn2700_simx-r0/platform_reboot
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700_simx-r0/plugins b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/plugins
new file mode 120000
index 000000000000..e98a1d3fbaeb
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/plugins
@@ -0,0 +1 @@
+../x86_64-mlnx_msn4700-r0/plugins
\ No newline at end of file
diff --git a/device/mellanox/x86_64-mlnx_msn4700_simx-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/pmon_daemon_control.json
new file mode 100644
index 000000000000..40fc367acf32
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/pmon_daemon_control.json
@@ -0,0 +1,5 @@
+{
+ "skip_ledd": true,
+ "skip_xcvrd": true,
+ "skip_psud": true
+}
diff --git a/device/mellanox/x86_64-mlnx_msn4700_simx-r0/syseeprom.hex b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/syseeprom.hex
new file mode 100644
index 000000000000..b50ffa5a0231
--- /dev/null
+++ b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/syseeprom.hex
@@ -0,0 +1,256 @@
+54 6c 76 49 6e 66 6f 00 01 02 53 21 40 4d 53 4e
+33 37 30 30 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 22 14 4d
+53 4e 33 37 30 30 2d 56 53 32 46 00 00 00 00 00
+00 00 00 23 18 4d 54 31 38 35 31 58 30 32 39 36
+31 00 00 00 00 00 00 00 00 00 00 00 00 24 06 98
+03 9b 94 d4 80 25 13 31 32 2f 32 38 2f 32 30 31
+38 20 30 34 3a 34 32 3a 31 38 26 01 00 2a 02 00
+fe 2b 08 4d 65 6c 6c 61 6e 6f 78 fd 24 00 00 81
+19 00 16 01 01 00 56 00 00 4d 4c 4e 58 02 01 0c
+05 0e 02 10 06 12 07 00 00 00 00 00 00 00 00 00
+00 fd a4 00 00 81 19 00 92 00 03 01 01 00 00 4d
+54 31 38 35 31 58 30 32 39 36 31 00 00 00 00 00
+00 00 00 00 00 00 00 4d 53 4e 33 37 30 30 2d 56
+53 32 46 00 00 00 00 00 00 00 00 41 32 00 00 00
+3a 82 b8 41 6e 61 63 6f 6e 64 61 20 45 74 68 20
+32 30 30 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 70 00 00 00 0e 74 4d 53 4e 33 37
+30 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 fd 24 00 00 81 19 00 10 00
+03 05 e8 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 fd 24 00
+00 81 19 00 1e 00 11 02 85 00 00 0d 00 00 00 00
+00 00 00 98 03 9b 94 d4 80 00 fe 98 03 9b 03 00
+94 d4 80 fd 24 00 00 81 19 00 12 00 01 06 81 00
+00 00 46 00 00 08 00 06 06 06 06 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 fd 14 00 00 81 19 00
+0e 00 02 07 99 00 00 30 00 20 00 00 00 00 00 28
+40 78 38 36 5f 36 34 2d 6d 6c 6e 78 5f 6d 73 6e
+33 37 30 30 2d 72 30 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 29 15 32 30 31 38 2e 31 31 2d 35 2e 32 2e 30
+30 30 38 2d 39 36 30 30 fe 04 89 cb 82 5b 00 00
+00 00 00 fe 04 72 60 7f 13 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/asic.conf b/device/virtual/x86_64-kvm_x86_64-r0/asic.conf
new file mode 100644
index 000000000000..58c5d5348bb9
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/asic.conf
@@ -0,0 +1 @@
+NUM_ASIC=1
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/buffers.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/buffers.json.j2
new file mode 100644
index 000000000000..b67cf577ab75
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/buffers.json.j2
@@ -0,0 +1,3 @@
+{%- set default_topo = 't1' %}
+{%- include 'buffers_config.j2' %}
+
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/buffers_defaults_def.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/buffers_defaults_def.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/buffers_defaults_def.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/buffers_defaults_t0.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/buffers_defaults_t0.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/buffers_defaults_t0.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/buffers_defaults_t1.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/buffers_defaults_t1.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/buffers_defaults_t1.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/lanemap.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/lanemap.ini
new file mode 100644
index 000000000000..36278a01778c
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/lanemap.ini
@@ -0,0 +1,32 @@
+eth1:25,26,27,28
+eth2:29,30,31,32
+eth3:33,34,35,36
+eth4:37,38,39,40
+eth5:45,46,47,48
+eth6:41,42,43,44
+eth7:1,2,3,4
+eth8:5,6,7,8
+eth9:13,14,15,16
+eth10:9,10,11,12
+eth11:17,18,19,20
+eth12:21,22,23,24
+eth13:53,54,55,56
+eth14:49,50,51,52
+eth15:57,58,59,60
+eth16:61,62,63,64
+eth17:69,70,71,72
+eth18:65,66,67,68
+eth19:73,74,75,76
+eth20:77,78,79,80
+eth21:109,110,111,112
+eth22:105,106,107,108
+eth23:113,114,115,116
+eth24:117,118,119,120
+eth25:125,126,127,128
+eth26:121,122,123,124
+eth27:81,82,83,84
+eth28:85,86,87,88
+eth29:93,94,95,96
+eth30:89,90,91,92
+eth31:101,102,103,104
+eth32:97,98,99,100
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/pg_profile_lookup.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/pg_profile_lookup.ini
new file mode 100644
index 000000000000..9f2eacb6fc42
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/pg_profile_lookup.ini
@@ -0,0 +1,17 @@
+# PG lossless profiles.
+# speed cable size xon xoff threshold xon_offset
+ 10000 5m 56368 18432 55120 -3 2496
+ 25000 5m 56368 18432 55120 -3 2496
+ 40000 5m 56368 18432 55120 -3 2496
+ 50000 5m 56368 18432 55120 -3 2496
+ 100000 5m 56368 18432 55120 -3 2496
+ 10000 40m 56368 18432 55120 -3 2496
+ 25000 40m 56368 18432 55120 -3 2496
+ 40000 40m 56368 18432 55120 -3 2496
+ 50000 40m 56368 18432 55120 -3 2496
+ 100000 40m 56368 18432 55120 -3 2496
+ 10000 300m 56368 18432 55120 -3 2496
+ 25000 300m 56368 18432 55120 -3 2496
+ 40000 300m 56368 18432 55120 -3 2496
+ 50000 300m 56368 18432 55120 -3 2496
+ 100000 300m 56368 18432 55120 -3 2496
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/port_config.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/port_config.ini
new file mode 100644
index 000000000000..95cf5eec9e4e
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/port_config.ini
@@ -0,0 +1,33 @@
+# name lanes alias index speed
+Ethernet0 25,26,27,28 fortyGigE0/0 0 40000
+Ethernet4 29,30,31,32 fortyGigE0/4 1 40000
+Ethernet8 33,34,35,36 fortyGigE0/8 2 40000
+Ethernet12 37,38,39,40 fortyGigE0/12 3 40000
+Ethernet16 45,46,47,48 fortyGigE0/16 4 40000
+Ethernet20 41,42,43,44 fortyGigE0/20 5 40000
+Ethernet24 1,2,3,4 fortyGigE0/24 6 40000
+Ethernet28 5,6,7,8 fortyGigE0/28 7 40000
+Ethernet32 13,14,15,16 fortyGigE0/32 8 40000
+Ethernet36 9,10,11,12 fortyGigE0/36 9 40000
+Ethernet40 17,18,19,20 fortyGigE0/40 10 40000
+Ethernet44 21,22,23,24 fortyGigE0/44 11 40000
+Ethernet48 53,54,55,56 fortyGigE0/48 12 40000
+Ethernet52 49,50,51,52 fortyGigE0/52 13 40000
+Ethernet56 57,58,59,60 fortyGigE0/56 14 40000
+Ethernet60 61,62,63,64 fortyGigE0/60 15 40000
+Ethernet64 69,70,71,72 fortyGigE0/64 16 40000
+Ethernet68 65,66,67,68 fortyGigE0/68 17 40000
+Ethernet72 73,74,75,76 fortyGigE0/72 18 40000
+Ethernet76 77,78,79,80 fortyGigE0/76 19 40000
+Ethernet80 109,110,111,112 fortyGigE0/80 20 40000
+Ethernet84 105,106,107,108 fortyGigE0/84 21 40000
+Ethernet88 113,114,115,116 fortyGigE0/88 22 40000
+Ethernet92 117,118,119,120 fortyGigE0/92 23 40000
+Ethernet96 125,126,127,128 fortyGigE0/96 24 40000
+Ethernet100 121,122,123,124 fortyGigE0/100 25 40000
+Ethernet104 81,82,83,84 fortyGigE0/104 26 40000
+Ethernet108 85,86,87,88 fortyGigE0/108 27 40000
+Ethernet112 93,94,95,96 fortyGigE0/112 28 40000
+Ethernet116 89,90,91,92 fortyGigE0/116 29 40000
+Ethernet120 101,102,103,104 fortyGigE0/120 30 40000
+Ethernet124 97,98,99,100 fortyGigE0/124 31 40000
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/qos.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/qos.json.j2
new file mode 100644
index 000000000000..3e548325ea30
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/qos.json.j2
@@ -0,0 +1 @@
+{%- include 'qos_config.j2' %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/sai.profile b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/sai.profile
new file mode 100644
index 000000000000..bfc466f27e54
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/sai.profile
@@ -0,0 +1,5 @@
+SAI_WARM_BOOT_READ_FILE=/var/cache/sai_warmboot.bin
+SAI_WARM_BOOT_WRITE_FILE=/var/cache/sai_warmboot.bin
+SAI_VS_SWITCH_TYPE=SAI_VS_SWITCH_TYPE_BCM56850
+SAI_VS_HOSTIF_USE_TAP_DEVICE=true
+SAI_VS_INTERFACE_LANE_MAP_FILE=/usr/share/sonic/hwsku/lanemap.ini
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/td2-s6000-32x40G.config.bcm b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/td2-s6000-32x40G.config.bcm
new file mode 100644
index 000000000000..4c94db7107c7
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/td2-s6000-32x40G.config.bcm
@@ -0,0 +1,646 @@
+# Old LPM only configuration
+# l2_mem_entries=163840
+# l3_mem_entries=90112
+# l3_alpm_enable=0
+# ipv6_lpm_128b_enable=0
+#
+# ALPM enable
+l3_alpm_enable=2
+ipv6_lpm_128b_enable=1
+l2_mem_entries=32768
+l3_mem_entries=16384
+
+# From old config file
+os=unix
+higig2_hdr_mode=1
+
+# Parity
+parity_correction=1
+parity_enable=1
+stat_if_parity_enable=0
+
+#
+bcm_num_cos=8
+bcm_stat_interval=2000000
+l2xmsg_hostbuf_size=8192
+l2xmsg_mode=1
+lls_num_l2uc=12
+max_vp_lags=0
+miim_intr_enable=0
+mmu_lossless=0
+module_64ports=0
+schan_intr_enable=0
+stable_size=0x2000000
+tdma_timeout_usec=5000000
+
+pbmp_oversubscribe=0x000007fffffffffffffffffffffffffe
+pbmp_xport_xe=0x000007fffffffffffffffffffffffffe
+
+# Ports configuration
+# xe0 (40G)
+portmap_1=25:40
+xgxs_rx_lane_map_1=0x213
+xgxs_tx_lane_map_1=0x2031
+phy_xaui_rx_polarity_flip_1=0xe
+phy_xaui_tx_polarity_flip_1=0x2
+serdes_driver_current_lane0_xe0=0x5
+serdes_driver_current_lane1_xe0=0x5
+serdes_driver_current_lane2_xe0=0x5
+serdes_driver_current_lane3_xe0=0x5
+serdes_pre_driver_current_lane0_xe0=0x5
+serdes_pre_driver_current_lane1_xe0=0x5
+serdes_pre_driver_current_lane2_xe0=0x5
+serdes_pre_driver_current_lane3_xe0=0x5
+serdes_preemphasis_lane0_xe0=0xcad0
+serdes_preemphasis_lane1_xe0=0xc6e0
+serdes_preemphasis_lane2_xe0=0xc6e0
+serdes_preemphasis_lane3_xe0=0xd2b0
+
+# xe1 (40G)
+portmap_2=29:40
+xgxs_rx_lane_map_2=0x213
+xgxs_tx_lane_map_2=0x213
+phy_xaui_rx_polarity_flip_2=0xc
+phy_xaui_tx_polarity_flip_2=0x9
+serdes_driver_current_lane0_xe1=0x6
+serdes_driver_current_lane1_xe1=0x7
+serdes_driver_current_lane2_xe1=0x6
+serdes_driver_current_lane3_xe1=0x6
+serdes_pre_driver_current_lane0_xe1=0x6
+serdes_pre_driver_current_lane1_xe1=0x7
+serdes_pre_driver_current_lane2_xe1=0x6
+serdes_pre_driver_current_lane3_xe1=0x6
+serdes_preemphasis_lane0_xe1=0xc2f0
+serdes_preemphasis_lane1_xe1=0xd2b0
+serdes_preemphasis_lane2_xe1=0xc6e0
+serdes_preemphasis_lane3_xe1=0xc2f0
+
+# xe2 (40G)
+portmap_3=33:40
+xgxs_rx_lane_map_3=0x213
+xgxs_tx_lane_map_3=0x132
+phy_xaui_rx_polarity_flip_3=0xe
+phy_xaui_tx_polarity_flip_3=0x2
+serdes_driver_current_lane0_xe2=0x4
+serdes_driver_current_lane1_xe2=0x4
+serdes_driver_current_lane2_xe2=0x4
+serdes_driver_current_lane3_xe2=0x4
+serdes_pre_driver_current_lane0_xe2=0x4
+serdes_pre_driver_current_lane1_xe2=0x4
+serdes_pre_driver_current_lane2_xe2=0x4
+serdes_pre_driver_current_lane3_xe2=0x4
+serdes_preemphasis_lane0_xe2=0xc6e0
+serdes_preemphasis_lane1_xe2=0xc6e0
+serdes_preemphasis_lane2_xe2=0xc6e0
+serdes_preemphasis_lane3_xe2=0xc6e0
+
+# xe3 (40G)
+portmap_4=37:40
+xgxs_rx_lane_map_4=0x213
+xgxs_tx_lane_map_4=0x1203
+phy_xaui_rx_polarity_flip_4=0x3
+phy_xaui_tx_polarity_flip_4=0xe
+serdes_driver_current_lane0_xe3=0x4
+serdes_driver_current_lane1_xe3=0x4
+serdes_driver_current_lane2_xe3=0x4
+serdes_driver_current_lane3_xe3=0x4
+serdes_pre_driver_current_lane0_xe3=0x4
+serdes_pre_driver_current_lane1_xe3=0x4
+serdes_pre_driver_current_lane2_xe3=0x4
+serdes_pre_driver_current_lane3_xe3=0x4
+serdes_preemphasis_lane0_xe3=0xcad0
+serdes_preemphasis_lane1_xe3=0xcad0
+serdes_preemphasis_lane2_xe3=0xc2f0
+serdes_preemphasis_lane3_xe3=0xc2f0
+
+# xe4 (40G)
+portmap_5=45:40
+xgxs_rx_lane_map_5=0x213
+xgxs_tx_lane_map_5=0x213
+phy_xaui_rx_polarity_flip_5=0xe
+phy_xaui_tx_polarity_flip_5=0x8
+serdes_driver_current_lane0_xe4=0x4
+serdes_driver_current_lane1_xe4=0x4
+serdes_driver_current_lane2_xe4=0x4
+serdes_driver_current_lane3_xe4=0x4
+serdes_pre_driver_current_lane0_xe4=0x4
+serdes_pre_driver_current_lane1_xe4=0x4
+serdes_pre_driver_current_lane2_xe4=0x4
+serdes_pre_driver_current_lane3_xe4=0x4
+serdes_preemphasis_lane0_xe4=0xc2f0
+serdes_preemphasis_lane1_xe4=0xc2f0
+serdes_preemphasis_lane2_xe4=0xc2f0
+serdes_preemphasis_lane3_xe4=0xc2f0
+
+# xe5 (40G)
+portmap_6=41:40
+xgxs_rx_lane_map_6=0x213
+xgxs_tx_lane_map_6=0x3021
+phy_xaui_rx_polarity_flip_6=0x3
+phy_xaui_tx_polarity_flip_6=0xb
+serdes_driver_current_lane0_xe5=0x4
+serdes_driver_current_lane1_xe5=0x4
+serdes_driver_current_lane2_xe5=0x4
+serdes_driver_current_lane3_xe5=0x4
+serdes_pre_driver_current_lane0_xe5=0x4
+serdes_pre_driver_current_lane1_xe5=0x4
+serdes_pre_driver_current_lane2_xe5=0x4
+serdes_pre_driver_current_lane3_xe5=0x4
+serdes_preemphasis_lane0_xe5=0xc6e0
+serdes_preemphasis_lane1_xe5=0xc2f0
+serdes_preemphasis_lane2_xe5=0xc2f0
+serdes_preemphasis_lane3_xe5=0xcad0
+
+# xe6 (40G)
+portmap_7=1:40
+xgxs_rx_lane_map_7=0x213
+xgxs_tx_lane_map_7=0x2031
+phy_xaui_rx_polarity_flip_7=0xe
+phy_xaui_tx_polarity_flip_7=0xd
+serdes_driver_current_lane0_xe6=0x5
+serdes_driver_current_lane1_xe6=0x5
+serdes_driver_current_lane2_xe6=0x5
+serdes_driver_current_lane3_xe6=0x5
+serdes_pre_driver_current_lane0_xe6=0x5
+serdes_pre_driver_current_lane1_xe6=0x5
+serdes_pre_driver_current_lane2_xe6=0x5
+serdes_pre_driver_current_lane3_xe6=0x5
+serdes_preemphasis_lane0_xe6=0xc6e0
+serdes_preemphasis_lane1_xe6=0xcad0
+serdes_preemphasis_lane2_xe6=0xc6e0
+serdes_preemphasis_lane3_xe6=0xcad0
+
+# xe7 (40G)
+portmap_8=5:40
+xgxs_rx_lane_map_8=0x213
+xgxs_tx_lane_map_8=0x1203
+phy_xaui_rx_polarity_flip_8=0xc
+phy_xaui_tx_polarity_flip_8=0x1
+serdes_driver_current_lane0_xe7=0x4
+serdes_driver_current_lane1_xe7=0x4
+serdes_driver_current_lane2_xe7=0x4
+serdes_driver_current_lane3_xe7=0x4
+serdes_pre_driver_current_lane0_xe7=0x4
+serdes_pre_driver_current_lane1_xe7=0x4
+serdes_pre_driver_current_lane2_xe7=0x4
+serdes_pre_driver_current_lane3_xe7=0x4
+serdes_preemphasis_lane0_xe7=0xc6e0
+serdes_preemphasis_lane1_xe7=0xc6e0
+serdes_preemphasis_lane2_xe7=0xc6e0
+serdes_preemphasis_lane3_xe7=0xc6e0
+
+# xe8 (40G)
+portmap_9=13:40
+xgxs_rx_lane_map_9=0x213
+xgxs_tx_lane_map_9=0x132
+phy_xaui_rx_polarity_flip_9=0xe
+phy_xaui_tx_polarity_flip_9=0x0
+serdes_driver_current_lane0_xe8=0x2
+serdes_driver_current_lane1_xe8=0x3
+serdes_driver_current_lane2_xe8=0x2
+serdes_driver_current_lane3_xe8=0x2
+serdes_pre_driver_current_lane0_xe8=0x2
+serdes_pre_driver_current_lane1_xe8=0x3
+serdes_pre_driver_current_lane2_xe8=0x2
+serdes_pre_driver_current_lane3_xe8=0x2
+serdes_preemphasis_lane0_xe8=0xb270
+serdes_preemphasis_lane1_xe8=0xbb10
+serdes_preemphasis_lane2_xe8=0xb720
+serdes_preemphasis_lane3_xe8=0xb720
+
+# xe9 (40G)
+portmap_10=9:40
+xgxs_rx_lane_map_10=0x3120
+xgxs_tx_lane_map_10=0x3021
+phy_xaui_rx_polarity_flip_10=0x0
+phy_xaui_tx_polarity_flip_10=0x4
+serdes_driver_current_lane0_xe9=0x3
+serdes_driver_current_lane1_xe9=0x3
+serdes_driver_current_lane2_xe9=0x3
+serdes_driver_current_lane3_xe9=0x3
+serdes_pre_driver_current_lane0_xe9=0x3
+serdes_pre_driver_current_lane1_xe9=0x3
+serdes_pre_driver_current_lane2_xe9=0x3
+serdes_pre_driver_current_lane3_xe9=0x3
+serdes_preemphasis_lane0_xe9=0xc2f0
+serdes_preemphasis_lane1_xe9=0xc6e0
+serdes_preemphasis_lane2_xe9=0xbf00
+serdes_preemphasis_lane3_xe9=0xc2f0
+
+# xe10 (40G)
+portmap_11=17:40
+xgxs_rx_lane_map_11=0x213
+xgxs_tx_lane_map_11=0x132
+phy_xaui_rx_polarity_flip_11=0xe
+phy_xaui_tx_polarity_flip_11=0x0
+serdes_driver_current_lane0_xe10=0x2
+serdes_driver_current_lane1_xe10=0x2
+serdes_driver_current_lane2_xe10=0x2
+serdes_driver_current_lane3_xe10=0x2
+serdes_pre_driver_current_lane0_xe10=0x2
+serdes_pre_driver_current_lane1_xe10=0x2
+serdes_pre_driver_current_lane2_xe10=0x2
+serdes_pre_driver_current_lane3_xe10=0x2
+serdes_preemphasis_lane0_xe10=0xb330
+serdes_preemphasis_lane1_xe10=0xbb10
+serdes_preemphasis_lane2_xe10=0xbb10
+serdes_preemphasis_lane3_xe10=0xbb10
+
+# xe11 (40G)
+portmap_12=21:40
+xgxs_rx_lane_map_12=0x123
+xgxs_tx_lane_map_12=0x1203
+phy_xaui_rx_polarity_flip_12=0xc
+phy_xaui_tx_polarity_flip_12=0xe
+serdes_driver_current_lane0_xe11=0x2
+serdes_driver_current_lane1_xe11=0x2
+serdes_driver_current_lane2_xe11=0x2
+serdes_driver_current_lane3_xe11=0x2
+serdes_pre_driver_current_lane0_xe11=0x2
+serdes_pre_driver_current_lane1_xe11=0x2
+serdes_pre_driver_current_lane2_xe11=0x2
+serdes_pre_driver_current_lane3_xe11=0x2
+serdes_preemphasis_lane0_xe11=0xb330
+serdes_preemphasis_lane1_xe11=0xb330
+serdes_preemphasis_lane2_xe11=0xb330
+serdes_preemphasis_lane3_xe11=0xb330
+
+# xe12 (40G)
+portmap_13=53:40
+xgxs_rx_lane_map_13=0x213
+xgxs_tx_lane_map_13=0x231
+phy_xaui_rx_polarity_flip_13=0x1
+phy_xaui_tx_polarity_flip_13=0x0
+serdes_driver_current_lane0_xe12=0x2
+serdes_driver_current_lane1_xe12=0x2
+serdes_driver_current_lane2_xe12=0x2
+serdes_driver_current_lane3_xe12=0x2
+serdes_pre_driver_current_lane0_xe12=0x2
+serdes_pre_driver_current_lane1_xe12=0x2
+serdes_pre_driver_current_lane2_xe12=0x2
+serdes_pre_driver_current_lane3_xe12=0x2
+serdes_preemphasis_lane0_xe12=0xaf40
+serdes_preemphasis_lane1_xe12=0xaf40
+serdes_preemphasis_lane2_xe12=0xaf40
+serdes_preemphasis_lane3_xe12=0xaf40
+
+# xe13 (40G)
+portmap_14=49:40
+xgxs_rx_lane_map_14=0x1302
+xgxs_tx_lane_map_14=0x2031
+phy_xaui_rx_polarity_flip_14=0xb
+phy_xaui_tx_polarity_flip_14=0x3
+serdes_driver_current_lane0_xe13=0x2
+serdes_driver_current_lane1_xe13=0x2
+serdes_driver_current_lane2_xe13=0x2
+serdes_driver_current_lane3_xe13=0x2
+serdes_pre_driver_current_lane0_xe13=0x2
+serdes_pre_driver_current_lane1_xe13=0x2
+serdes_pre_driver_current_lane2_xe13=0x2
+serdes_pre_driver_current_lane3_xe13=0x2
+serdes_preemphasis_lane0_xe13=0xa760
+serdes_preemphasis_lane1_xe13=0xa760
+serdes_preemphasis_lane2_xe13=0xa760
+serdes_preemphasis_lane3_xe13=0xa760
+
+# xe14 (40G)
+portmap_15=57:40
+xgxs_rx_lane_map_15=0x213
+xgxs_tx_lane_map_15=0x2031
+phy_xaui_rx_polarity_flip_15=0x1
+phy_xaui_tx_polarity_flip_15=0x0
+serdes_driver_current_lane0_xe14=0x1
+serdes_driver_current_lane1_xe14=0x1
+serdes_driver_current_lane2_xe14=0x1
+serdes_driver_current_lane3_xe14=0x1
+serdes_pre_driver_current_lane0_xe14=0x1
+serdes_pre_driver_current_lane1_xe14=0x1
+serdes_pre_driver_current_lane2_xe14=0x1
+serdes_pre_driver_current_lane3_xe14=0x1
+serdes_preemphasis_lane0_xe14=0xa760
+serdes_preemphasis_lane1_xe14=0xa760
+serdes_preemphasis_lane2_xe14=0xa760
+serdes_preemphasis_lane3_xe14=0xa760
+
+# xe15 (40G)
+portmap_16=61:40
+xgxs_rx_lane_map_16=0x132
+xgxs_tx_lane_map_16=0x213
+phy_xaui_rx_polarity_flip_16=0x0
+phy_xaui_tx_polarity_flip_16=0x0
+serdes_driver_current_lane0_xe15=0x2
+serdes_driver_current_lane1_xe15=0x2
+serdes_driver_current_lane2_xe15=0x2
+serdes_driver_current_lane3_xe15=0x2
+serdes_pre_driver_current_lane0_xe15=0x2
+serdes_pre_driver_current_lane1_xe15=0x2
+serdes_pre_driver_current_lane2_xe15=0x2
+serdes_pre_driver_current_lane3_xe15=0x2
+serdes_preemphasis_lane0_xe15=0xa760
+serdes_preemphasis_lane1_xe15=0xa760
+serdes_preemphasis_lane2_xe15=0xa760
+serdes_preemphasis_lane3_xe15=0xa760
+
+# xe16 (40G)
+portmap_17=69:40
+xgxs_rx_lane_map_17=0x213
+xgxs_tx_lane_map_17=0x2130
+phy_xaui_rx_polarity_flip_17=0x1
+phy_xaui_tx_polarity_flip_17=0xf
+serdes_driver_current_lane0_xe16=0x1
+serdes_driver_current_lane1_xe16=0x1
+serdes_driver_current_lane2_xe16=0x1
+serdes_driver_current_lane3_xe16=0x1
+serdes_pre_driver_current_lane0_xe16=0x1
+serdes_pre_driver_current_lane1_xe16=0x1
+serdes_pre_driver_current_lane2_xe16=0x1
+serdes_pre_driver_current_lane3_xe16=0x1
+serdes_preemphasis_lane0_xe16=0xa760
+serdes_preemphasis_lane1_xe16=0xa760
+serdes_preemphasis_lane2_xe16=0xa760
+serdes_preemphasis_lane3_xe16=0xa760
+
+# xe17 (40G)
+portmap_18=65:40
+xgxs_rx_lane_map_18=0x132
+xgxs_tx_lane_map_18=0x2031
+phy_xaui_rx_polarity_flip_18=0x3
+phy_xaui_tx_polarity_flip_18=0x9
+serdes_driver_current_lane0_xe17=0x1
+serdes_driver_current_lane1_xe17=0x1
+serdes_driver_current_lane2_xe17=0x1
+serdes_driver_current_lane3_xe17=0x1
+serdes_pre_driver_current_lane0_xe17=0x1
+serdes_pre_driver_current_lane1_xe17=0x1
+serdes_pre_driver_current_lane2_xe17=0x1
+serdes_pre_driver_current_lane3_xe17=0x1
+serdes_preemphasis_lane0_xe17=0xa370
+serdes_preemphasis_lane1_xe17=0xa370
+serdes_preemphasis_lane2_xe17=0xa370
+serdes_preemphasis_lane3_xe17=0xa370
+
+# xe18 (40G)
+portmap_19=73:40
+xgxs_rx_lane_map_19=0x213
+xgxs_tx_lane_map_19=0x2031
+phy_xaui_rx_polarity_flip_19=0x1
+phy_xaui_tx_polarity_flip_19=0x0
+serdes_driver_current_lane0_xe18=0x2
+serdes_driver_current_lane1_xe18=0x2
+serdes_driver_current_lane2_xe18=0x2
+serdes_driver_current_lane3_xe18=0x2
+serdes_pre_driver_current_lane0_xe18=0x2
+serdes_pre_driver_current_lane1_xe18=0x2
+serdes_pre_driver_current_lane2_xe18=0x2
+serdes_pre_driver_current_lane3_xe18=0x2
+serdes_preemphasis_lane0_xe18=0xa760
+serdes_preemphasis_lane1_xe18=0xa760
+serdes_preemphasis_lane2_xe18=0xa760
+serdes_preemphasis_lane3_xe18=0xa760
+
+# xe19 (40G)
+portmap_20=77:40
+xgxs_rx_lane_map_20=0x123
+xgxs_tx_lane_map_20=0x1203
+phy_xaui_rx_polarity_flip_20=0x3
+phy_xaui_tx_polarity_flip_20=0xe
+serdes_driver_current_lane0_xe19=0x2
+serdes_driver_current_lane1_xe19=0x2
+serdes_driver_current_lane2_xe19=0x2
+serdes_driver_current_lane3_xe19=0x2
+serdes_pre_driver_current_lane0_xe19=0x2
+serdes_pre_driver_current_lane1_xe19=0x2
+serdes_pre_driver_current_lane2_xe19=0x2
+serdes_pre_driver_current_lane3_xe19=0x2
+serdes_preemphasis_lane0_xe19=0xaf40
+serdes_preemphasis_lane1_xe19=0xaf40
+serdes_preemphasis_lane2_xe19=0xaf40
+serdes_preemphasis_lane3_xe19=0xaf40
+
+# xe20 (40G)
+portmap_21=109:40
+xgxs_rx_lane_map_21=0x132
+xgxs_tx_lane_map_21=0x132
+phy_xaui_rx_polarity_flip_21=0x8
+phy_xaui_tx_polarity_flip_21=0x0
+serdes_driver_current_lane0_xe20=0x1
+serdes_driver_current_lane1_xe20=0x1
+serdes_driver_current_lane2_xe20=0x1
+serdes_driver_current_lane3_xe20=0x2
+serdes_pre_driver_current_lane0_xe20=0x1
+serdes_pre_driver_current_lane1_xe20=0x1
+serdes_pre_driver_current_lane2_xe20=0x1
+serdes_pre_driver_current_lane3_xe20=0x2
+serdes_preemphasis_lane0_xe20=0xb330
+serdes_preemphasis_lane1_xe20=0xb330
+serdes_preemphasis_lane2_xe20=0xb330
+serdes_preemphasis_lane3_xe20=0xbff0
+
+# xe21 (40G)
+portmap_22=105:40
+xgxs_rx_lane_map_22=0x1320
+xgxs_tx_lane_map_22=0x3021
+phy_xaui_rx_polarity_flip_22=0xd
+phy_xaui_tx_polarity_flip_22=0xb
+serdes_driver_current_lane0_xe21=0x1
+serdes_driver_current_lane1_xe21=0x1
+serdes_driver_current_lane2_xe21=0x1
+serdes_driver_current_lane3_xe21=0x1
+serdes_pre_driver_current_lane0_xe21=0x1
+serdes_pre_driver_current_lane1_xe21=0x1
+serdes_pre_driver_current_lane2_xe21=0x1
+serdes_pre_driver_current_lane3_xe21=0x1
+serdes_preemphasis_lane0_xe21=0xb330
+serdes_preemphasis_lane1_xe21=0xb330
+serdes_preemphasis_lane2_xe21=0xb330
+serdes_preemphasis_lane3_xe21=0xb330
+
+# xe22 (40G)
+portmap_23=113:40
+xgxs_rx_lane_map_23=0x132
+xgxs_tx_lane_map_23=0x132
+phy_xaui_rx_polarity_flip_23=0x8
+phy_xaui_tx_polarity_flip_23=0x0
+serdes_driver_current_lane0_xe22=0x1
+serdes_driver_current_lane1_xe22=0x1
+serdes_driver_current_lane2_xe22=0x1
+serdes_driver_current_lane3_xe22=0x1
+serdes_pre_driver_current_lane0_xe22=0x1
+serdes_pre_driver_current_lane1_xe22=0x1
+serdes_pre_driver_current_lane2_xe22=0x1
+serdes_pre_driver_current_lane3_xe22=0x1
+serdes_preemphasis_lane0_xe22=0xbb10
+serdes_preemphasis_lane1_xe22=0xbb10
+serdes_preemphasis_lane2_xe22=0xbb10
+serdes_preemphasis_lane3_xe22=0xc2f0
+
+# xe23 (40G)
+portmap_24=117:40
+xgxs_rx_lane_map_24=0x231
+xgxs_tx_lane_map_24=0x1203
+phy_xaui_rx_polarity_flip_24=0x3
+phy_xaui_tx_polarity_flip_24=0xe
+serdes_driver_current_lane0_xe23=0x3
+serdes_driver_current_lane1_xe23=0x5
+serdes_driver_current_lane2_xe23=0x3
+serdes_driver_current_lane3_xe23=0x3
+serdes_pre_driver_current_lane0_xe23=0x3
+serdes_pre_driver_current_lane1_xe23=0x5
+serdes_pre_driver_current_lane2_xe23=0x3
+serdes_pre_driver_current_lane3_xe23=0x3
+serdes_preemphasis_lane0_xe23=0xc6e0
+serdes_preemphasis_lane1_xe23=0xc6e0
+serdes_preemphasis_lane2_xe23=0xc6e0
+serdes_preemphasis_lane3_xe23=0xc6e0
+
+# xe24 (40G)
+portmap_25=125:40
+xgxs_rx_lane_map_25=0x132
+xgxs_tx_lane_map_25=0x132
+phy_xaui_rx_polarity_flip_25=0x8
+phy_xaui_tx_polarity_flip_25=0x0
+serdes_driver_current_lane0_xe24=0x4
+serdes_driver_current_lane1_xe24=0x4
+serdes_driver_current_lane2_xe24=0x4
+serdes_driver_current_lane3_xe24=0x4
+serdes_pre_driver_current_lane0_xe24=0x4
+serdes_pre_driver_current_lane1_xe24=0x4
+serdes_pre_driver_current_lane2_xe24=0x4
+serdes_pre_driver_current_lane3_xe24=0x4
+serdes_preemphasis_lane0_xe24=0xc6e0
+serdes_preemphasis_lane1_xe24=0xc6e0
+serdes_preemphasis_lane2_xe24=0xc6e0
+serdes_preemphasis_lane3_xe24=0xcec0
+
+# xe25 (40G)
+portmap_26=121:40
+xgxs_rx_lane_map_26=0x1320
+xgxs_tx_lane_map_26=0x3021
+phy_xaui_rx_polarity_flip_26=0xd
+phy_xaui_tx_polarity_flip_26=0xb
+serdes_driver_current_lane0_xe25=0x4
+serdes_driver_current_lane1_xe25=0x4
+serdes_driver_current_lane2_xe25=0x4
+serdes_driver_current_lane3_xe25=0x4
+serdes_pre_driver_current_lane0_xe25=0x4
+serdes_pre_driver_current_lane1_xe25=0x4
+serdes_pre_driver_current_lane2_xe25=0x4
+serdes_pre_driver_current_lane3_xe25=0x4
+serdes_preemphasis_lane0_xe25=0xc6e0
+serdes_preemphasis_lane1_xe25=0xc6e0
+serdes_preemphasis_lane2_xe25=0xc6e0
+serdes_preemphasis_lane3_xe25=0xc6e0
+
+# xe26 (40G)
+portmap_27=81:40
+xgxs_rx_lane_map_27=0x1320
+xgxs_tx_lane_map_27=0x2031
+phy_xaui_rx_polarity_flip_27=0x1
+phy_xaui_tx_polarity_flip_27=0x2
+serdes_driver_current_lane0_xe26=0x2
+serdes_driver_current_lane1_xe26=0x2
+serdes_driver_current_lane2_xe26=0x2
+serdes_driver_current_lane3_xe26=0x2
+serdes_pre_driver_current_lane0_xe26=0x2
+serdes_pre_driver_current_lane1_xe26=0x2
+serdes_pre_driver_current_lane2_xe26=0x2
+serdes_pre_driver_current_lane3_xe26=0x2
+serdes_preemphasis_lane0_xe26=0xbb10
+serdes_preemphasis_lane1_xe26=0xbb10
+serdes_preemphasis_lane2_xe26=0xbf00
+serdes_preemphasis_lane3_xe26=0xbb10
+
+# xe27 (40G)
+portmap_28=85:40
+xgxs_rx_lane_map_28=0x213
+xgxs_tx_lane_map_28=0x1203
+phy_xaui_rx_polarity_flip_28=0xc
+phy_xaui_tx_polarity_flip_28=0xe
+serdes_driver_current_lane0_xe27=0x4
+serdes_driver_current_lane1_xe27=0x5
+serdes_driver_current_lane2_xe27=0x4
+serdes_driver_current_lane3_xe27=0x5
+serdes_pre_driver_current_lane0_xe27=0x4
+serdes_pre_driver_current_lane1_xe27=0x5
+serdes_pre_driver_current_lane2_xe27=0x4
+serdes_pre_driver_current_lane3_xe27=0x5
+serdes_preemphasis_lane0_xe27=0xc2f0
+serdes_preemphasis_lane1_xe27=0xc6e0
+serdes_preemphasis_lane2_xe27=0xc6e0
+serdes_preemphasis_lane3_xe27=0xc6e0
+
+# xe28 (40G)
+portmap_29=93:40
+xgxs_rx_lane_map_29=0x1320
+xgxs_tx_lane_map_29=0x2031
+phy_xaui_rx_polarity_flip_29=0x1
+phy_xaui_tx_polarity_flip_29=0x2
+serdes_driver_current_lane0_xe28=0x4
+serdes_driver_current_lane1_xe28=0x4
+serdes_driver_current_lane2_xe28=0x4
+serdes_driver_current_lane3_xe28=0x4
+serdes_pre_driver_current_lane0_xe28=0x4
+serdes_pre_driver_current_lane1_xe28=0x4
+serdes_pre_driver_current_lane2_xe28=0x4
+serdes_pre_driver_current_lane3_xe28=0x4
+serdes_preemphasis_lane0_xe28=0xc2f0
+serdes_preemphasis_lane1_xe28=0xc2f0
+serdes_preemphasis_lane2_xe28=0xc2f0
+serdes_preemphasis_lane3_xe28=0xc2f0
+
+# xe29 (40G)
+portmap_30=89:40
+xgxs_rx_lane_map_30=0x1320
+xgxs_tx_lane_map_30=0x3021
+phy_xaui_rx_polarity_flip_30=0x2
+phy_xaui_tx_polarity_flip_30=0xb
+serdes_driver_current_lane0_xe29=0x4
+serdes_driver_current_lane1_xe29=0x4
+serdes_driver_current_lane2_xe29=0x4
+serdes_driver_current_lane3_xe29=0x4
+serdes_pre_driver_current_lane0_xe29=0x4
+serdes_pre_driver_current_lane1_xe29=0x4
+serdes_pre_driver_current_lane2_xe29=0x4
+serdes_pre_driver_current_lane3_xe29=0x4
+serdes_preemphasis_lane0_xe29=0xcad0
+serdes_preemphasis_lane1_xe29=0xc6e0
+serdes_preemphasis_lane2_xe29=0xc6e0
+serdes_preemphasis_lane3_xe29=0xc6e0
+
+# xe30 (40G)
+portmap_31=101:40
+xgxs_rx_lane_map_31=0x1320
+xgxs_tx_lane_map_31=0x1203
+phy_xaui_rx_polarity_flip_31=0x1
+phy_xaui_tx_polarity_flip_31=0x6
+serdes_driver_current_lane0_xe30=0x6
+serdes_driver_current_lane1_xe30=0x6
+serdes_driver_current_lane2_xe30=0x6
+serdes_driver_current_lane3_xe30=0x7
+serdes_pre_driver_current_lane0_xe30=0x6
+serdes_pre_driver_current_lane1_xe30=0x6
+serdes_pre_driver_current_lane2_xe30=0x6
+serdes_pre_driver_current_lane3_xe30=0x7
+serdes_preemphasis_lane0_xe30=0xcec0
+serdes_preemphasis_lane1_xe30=0xcec0
+serdes_preemphasis_lane2_xe30=0xcad0
+serdes_preemphasis_lane3_xe30=0xc6e0
+
+# xe31 (40G)
+portmap_32=97:40
+xgxs_rx_lane_map_32=0x213
+xgxs_tx_lane_map_32=0x2031
+phy_xaui_rx_polarity_flip_32=0xc
+phy_xaui_tx_polarity_flip_32=0x3
+serdes_driver_current_lane0_xe31=0x5
+serdes_driver_current_lane1_xe31=0x5
+serdes_driver_current_lane2_xe31=0x5
+serdes_driver_current_lane3_xe31=0x5
+serdes_pre_driver_current_lane0_xe31=0x5
+serdes_pre_driver_current_lane1_xe31=0x5
+serdes_pre_driver_current_lane2_xe31=0x5
+serdes_pre_driver_current_lane3_xe31=0x5
+serdes_preemphasis_lane0_xe31=0xcad0
+serdes_preemphasis_lane1_xe31=0xcad0
+serdes_preemphasis_lane2_xe31=0xcad0
+serdes_preemphasis_lane3_xe31=0xcad0
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/buffers.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/buffers.json.j2
new file mode 100644
index 000000000000..b67cf577ab75
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/buffers.json.j2
@@ -0,0 +1,3 @@
+{%- set default_topo = 't1' %}
+{%- include 'buffers_config.j2' %}
+
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/buffers_defaults_def.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/buffers_defaults_def.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/buffers_defaults_def.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/buffers_defaults_t0.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/buffers_defaults_t0.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/buffers_defaults_t0.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/buffers_defaults_t1.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/buffers_defaults_t1.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/buffers_defaults_t1.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/lanemap.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/lanemap.ini
new file mode 100644
index 000000000000..36278a01778c
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/lanemap.ini
@@ -0,0 +1,32 @@
+eth1:25,26,27,28
+eth2:29,30,31,32
+eth3:33,34,35,36
+eth4:37,38,39,40
+eth5:45,46,47,48
+eth6:41,42,43,44
+eth7:1,2,3,4
+eth8:5,6,7,8
+eth9:13,14,15,16
+eth10:9,10,11,12
+eth11:17,18,19,20
+eth12:21,22,23,24
+eth13:53,54,55,56
+eth14:49,50,51,52
+eth15:57,58,59,60
+eth16:61,62,63,64
+eth17:69,70,71,72
+eth18:65,66,67,68
+eth19:73,74,75,76
+eth20:77,78,79,80
+eth21:109,110,111,112
+eth22:105,106,107,108
+eth23:113,114,115,116
+eth24:117,118,119,120
+eth25:125,126,127,128
+eth26:121,122,123,124
+eth27:81,82,83,84
+eth28:85,86,87,88
+eth29:93,94,95,96
+eth30:89,90,91,92
+eth31:101,102,103,104
+eth32:97,98,99,100
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/pg_profile_lookup.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/pg_profile_lookup.ini
new file mode 100644
index 000000000000..9f2eacb6fc42
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/pg_profile_lookup.ini
@@ -0,0 +1,17 @@
+# PG lossless profiles.
+# speed cable size xon xoff threshold xon_offset
+ 10000 5m 56368 18432 55120 -3 2496
+ 25000 5m 56368 18432 55120 -3 2496
+ 40000 5m 56368 18432 55120 -3 2496
+ 50000 5m 56368 18432 55120 -3 2496
+ 100000 5m 56368 18432 55120 -3 2496
+ 10000 40m 56368 18432 55120 -3 2496
+ 25000 40m 56368 18432 55120 -3 2496
+ 40000 40m 56368 18432 55120 -3 2496
+ 50000 40m 56368 18432 55120 -3 2496
+ 100000 40m 56368 18432 55120 -3 2496
+ 10000 300m 56368 18432 55120 -3 2496
+ 25000 300m 56368 18432 55120 -3 2496
+ 40000 300m 56368 18432 55120 -3 2496
+ 50000 300m 56368 18432 55120 -3 2496
+ 100000 300m 56368 18432 55120 -3 2496
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/port_config.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/port_config.ini
new file mode 100644
index 000000000000..95cf5eec9e4e
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/port_config.ini
@@ -0,0 +1,33 @@
+# name lanes alias index speed
+Ethernet0 25,26,27,28 fortyGigE0/0 0 40000
+Ethernet4 29,30,31,32 fortyGigE0/4 1 40000
+Ethernet8 33,34,35,36 fortyGigE0/8 2 40000
+Ethernet12 37,38,39,40 fortyGigE0/12 3 40000
+Ethernet16 45,46,47,48 fortyGigE0/16 4 40000
+Ethernet20 41,42,43,44 fortyGigE0/20 5 40000
+Ethernet24 1,2,3,4 fortyGigE0/24 6 40000
+Ethernet28 5,6,7,8 fortyGigE0/28 7 40000
+Ethernet32 13,14,15,16 fortyGigE0/32 8 40000
+Ethernet36 9,10,11,12 fortyGigE0/36 9 40000
+Ethernet40 17,18,19,20 fortyGigE0/40 10 40000
+Ethernet44 21,22,23,24 fortyGigE0/44 11 40000
+Ethernet48 53,54,55,56 fortyGigE0/48 12 40000
+Ethernet52 49,50,51,52 fortyGigE0/52 13 40000
+Ethernet56 57,58,59,60 fortyGigE0/56 14 40000
+Ethernet60 61,62,63,64 fortyGigE0/60 15 40000
+Ethernet64 69,70,71,72 fortyGigE0/64 16 40000
+Ethernet68 65,66,67,68 fortyGigE0/68 17 40000
+Ethernet72 73,74,75,76 fortyGigE0/72 18 40000
+Ethernet76 77,78,79,80 fortyGigE0/76 19 40000
+Ethernet80 109,110,111,112 fortyGigE0/80 20 40000
+Ethernet84 105,106,107,108 fortyGigE0/84 21 40000
+Ethernet88 113,114,115,116 fortyGigE0/88 22 40000
+Ethernet92 117,118,119,120 fortyGigE0/92 23 40000
+Ethernet96 125,126,127,128 fortyGigE0/96 24 40000
+Ethernet100 121,122,123,124 fortyGigE0/100 25 40000
+Ethernet104 81,82,83,84 fortyGigE0/104 26 40000
+Ethernet108 85,86,87,88 fortyGigE0/108 27 40000
+Ethernet112 93,94,95,96 fortyGigE0/112 28 40000
+Ethernet116 89,90,91,92 fortyGigE0/116 29 40000
+Ethernet120 101,102,103,104 fortyGigE0/120 30 40000
+Ethernet124 97,98,99,100 fortyGigE0/124 31 40000
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/qos.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/qos.json.j2
new file mode 100644
index 000000000000..3e548325ea30
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/qos.json.j2
@@ -0,0 +1 @@
+{%- include 'qos_config.j2' %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/sai.profile b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/sai.profile
new file mode 100644
index 000000000000..bfc466f27e54
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/sai.profile
@@ -0,0 +1,5 @@
+SAI_WARM_BOOT_READ_FILE=/var/cache/sai_warmboot.bin
+SAI_WARM_BOOT_WRITE_FILE=/var/cache/sai_warmboot.bin
+SAI_VS_SWITCH_TYPE=SAI_VS_SWITCH_TYPE_BCM56850
+SAI_VS_HOSTIF_USE_TAP_DEVICE=true
+SAI_VS_INTERFACE_LANE_MAP_FILE=/usr/share/sonic/hwsku/lanemap.ini
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/td2-s6000-32x40G.config.bcm b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/td2-s6000-32x40G.config.bcm
new file mode 100644
index 000000000000..4c94db7107c7
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/td2-s6000-32x40G.config.bcm
@@ -0,0 +1,646 @@
+# Old LPM only configuration
+# l2_mem_entries=163840
+# l3_mem_entries=90112
+# l3_alpm_enable=0
+# ipv6_lpm_128b_enable=0
+#
+# ALPM enable
+l3_alpm_enable=2
+ipv6_lpm_128b_enable=1
+l2_mem_entries=32768
+l3_mem_entries=16384
+
+# From old config file
+os=unix
+higig2_hdr_mode=1
+
+# Parity
+parity_correction=1
+parity_enable=1
+stat_if_parity_enable=0
+
+#
+bcm_num_cos=8
+bcm_stat_interval=2000000
+l2xmsg_hostbuf_size=8192
+l2xmsg_mode=1
+lls_num_l2uc=12
+max_vp_lags=0
+miim_intr_enable=0
+mmu_lossless=0
+module_64ports=0
+schan_intr_enable=0
+stable_size=0x2000000
+tdma_timeout_usec=5000000
+
+pbmp_oversubscribe=0x000007fffffffffffffffffffffffffe
+pbmp_xport_xe=0x000007fffffffffffffffffffffffffe
+
+# Ports configuration
+# xe0 (40G)
+portmap_1=25:40
+xgxs_rx_lane_map_1=0x213
+xgxs_tx_lane_map_1=0x2031
+phy_xaui_rx_polarity_flip_1=0xe
+phy_xaui_tx_polarity_flip_1=0x2
+serdes_driver_current_lane0_xe0=0x5
+serdes_driver_current_lane1_xe0=0x5
+serdes_driver_current_lane2_xe0=0x5
+serdes_driver_current_lane3_xe0=0x5
+serdes_pre_driver_current_lane0_xe0=0x5
+serdes_pre_driver_current_lane1_xe0=0x5
+serdes_pre_driver_current_lane2_xe0=0x5
+serdes_pre_driver_current_lane3_xe0=0x5
+serdes_preemphasis_lane0_xe0=0xcad0
+serdes_preemphasis_lane1_xe0=0xc6e0
+serdes_preemphasis_lane2_xe0=0xc6e0
+serdes_preemphasis_lane3_xe0=0xd2b0
+
+# xe1 (40G)
+portmap_2=29:40
+xgxs_rx_lane_map_2=0x213
+xgxs_tx_lane_map_2=0x213
+phy_xaui_rx_polarity_flip_2=0xc
+phy_xaui_tx_polarity_flip_2=0x9
+serdes_driver_current_lane0_xe1=0x6
+serdes_driver_current_lane1_xe1=0x7
+serdes_driver_current_lane2_xe1=0x6
+serdes_driver_current_lane3_xe1=0x6
+serdes_pre_driver_current_lane0_xe1=0x6
+serdes_pre_driver_current_lane1_xe1=0x7
+serdes_pre_driver_current_lane2_xe1=0x6
+serdes_pre_driver_current_lane3_xe1=0x6
+serdes_preemphasis_lane0_xe1=0xc2f0
+serdes_preemphasis_lane1_xe1=0xd2b0
+serdes_preemphasis_lane2_xe1=0xc6e0
+serdes_preemphasis_lane3_xe1=0xc2f0
+
+# xe2 (40G)
+portmap_3=33:40
+xgxs_rx_lane_map_3=0x213
+xgxs_tx_lane_map_3=0x132
+phy_xaui_rx_polarity_flip_3=0xe
+phy_xaui_tx_polarity_flip_3=0x2
+serdes_driver_current_lane0_xe2=0x4
+serdes_driver_current_lane1_xe2=0x4
+serdes_driver_current_lane2_xe2=0x4
+serdes_driver_current_lane3_xe2=0x4
+serdes_pre_driver_current_lane0_xe2=0x4
+serdes_pre_driver_current_lane1_xe2=0x4
+serdes_pre_driver_current_lane2_xe2=0x4
+serdes_pre_driver_current_lane3_xe2=0x4
+serdes_preemphasis_lane0_xe2=0xc6e0
+serdes_preemphasis_lane1_xe2=0xc6e0
+serdes_preemphasis_lane2_xe2=0xc6e0
+serdes_preemphasis_lane3_xe2=0xc6e0
+
+# xe3 (40G)
+portmap_4=37:40
+xgxs_rx_lane_map_4=0x213
+xgxs_tx_lane_map_4=0x1203
+phy_xaui_rx_polarity_flip_4=0x3
+phy_xaui_tx_polarity_flip_4=0xe
+serdes_driver_current_lane0_xe3=0x4
+serdes_driver_current_lane1_xe3=0x4
+serdes_driver_current_lane2_xe3=0x4
+serdes_driver_current_lane3_xe3=0x4
+serdes_pre_driver_current_lane0_xe3=0x4
+serdes_pre_driver_current_lane1_xe3=0x4
+serdes_pre_driver_current_lane2_xe3=0x4
+serdes_pre_driver_current_lane3_xe3=0x4
+serdes_preemphasis_lane0_xe3=0xcad0
+serdes_preemphasis_lane1_xe3=0xcad0
+serdes_preemphasis_lane2_xe3=0xc2f0
+serdes_preemphasis_lane3_xe3=0xc2f0
+
+# xe4 (40G)
+portmap_5=45:40
+xgxs_rx_lane_map_5=0x213
+xgxs_tx_lane_map_5=0x213
+phy_xaui_rx_polarity_flip_5=0xe
+phy_xaui_tx_polarity_flip_5=0x8
+serdes_driver_current_lane0_xe4=0x4
+serdes_driver_current_lane1_xe4=0x4
+serdes_driver_current_lane2_xe4=0x4
+serdes_driver_current_lane3_xe4=0x4
+serdes_pre_driver_current_lane0_xe4=0x4
+serdes_pre_driver_current_lane1_xe4=0x4
+serdes_pre_driver_current_lane2_xe4=0x4
+serdes_pre_driver_current_lane3_xe4=0x4
+serdes_preemphasis_lane0_xe4=0xc2f0
+serdes_preemphasis_lane1_xe4=0xc2f0
+serdes_preemphasis_lane2_xe4=0xc2f0
+serdes_preemphasis_lane3_xe4=0xc2f0
+
+# xe5 (40G)
+portmap_6=41:40
+xgxs_rx_lane_map_6=0x213
+xgxs_tx_lane_map_6=0x3021
+phy_xaui_rx_polarity_flip_6=0x3
+phy_xaui_tx_polarity_flip_6=0xb
+serdes_driver_current_lane0_xe5=0x4
+serdes_driver_current_lane1_xe5=0x4
+serdes_driver_current_lane2_xe5=0x4
+serdes_driver_current_lane3_xe5=0x4
+serdes_pre_driver_current_lane0_xe5=0x4
+serdes_pre_driver_current_lane1_xe5=0x4
+serdes_pre_driver_current_lane2_xe5=0x4
+serdes_pre_driver_current_lane3_xe5=0x4
+serdes_preemphasis_lane0_xe5=0xc6e0
+serdes_preemphasis_lane1_xe5=0xc2f0
+serdes_preemphasis_lane2_xe5=0xc2f0
+serdes_preemphasis_lane3_xe5=0xcad0
+
+# xe6 (40G)
+portmap_7=1:40
+xgxs_rx_lane_map_7=0x213
+xgxs_tx_lane_map_7=0x2031
+phy_xaui_rx_polarity_flip_7=0xe
+phy_xaui_tx_polarity_flip_7=0xd
+serdes_driver_current_lane0_xe6=0x5
+serdes_driver_current_lane1_xe6=0x5
+serdes_driver_current_lane2_xe6=0x5
+serdes_driver_current_lane3_xe6=0x5
+serdes_pre_driver_current_lane0_xe6=0x5
+serdes_pre_driver_current_lane1_xe6=0x5
+serdes_pre_driver_current_lane2_xe6=0x5
+serdes_pre_driver_current_lane3_xe6=0x5
+serdes_preemphasis_lane0_xe6=0xc6e0
+serdes_preemphasis_lane1_xe6=0xcad0
+serdes_preemphasis_lane2_xe6=0xc6e0
+serdes_preemphasis_lane3_xe6=0xcad0
+
+# xe7 (40G)
+portmap_8=5:40
+xgxs_rx_lane_map_8=0x213
+xgxs_tx_lane_map_8=0x1203
+phy_xaui_rx_polarity_flip_8=0xc
+phy_xaui_tx_polarity_flip_8=0x1
+serdes_driver_current_lane0_xe7=0x4
+serdes_driver_current_lane1_xe7=0x4
+serdes_driver_current_lane2_xe7=0x4
+serdes_driver_current_lane3_xe7=0x4
+serdes_pre_driver_current_lane0_xe7=0x4
+serdes_pre_driver_current_lane1_xe7=0x4
+serdes_pre_driver_current_lane2_xe7=0x4
+serdes_pre_driver_current_lane3_xe7=0x4
+serdes_preemphasis_lane0_xe7=0xc6e0
+serdes_preemphasis_lane1_xe7=0xc6e0
+serdes_preemphasis_lane2_xe7=0xc6e0
+serdes_preemphasis_lane3_xe7=0xc6e0
+
+# xe8 (40G)
+portmap_9=13:40
+xgxs_rx_lane_map_9=0x213
+xgxs_tx_lane_map_9=0x132
+phy_xaui_rx_polarity_flip_9=0xe
+phy_xaui_tx_polarity_flip_9=0x0
+serdes_driver_current_lane0_xe8=0x2
+serdes_driver_current_lane1_xe8=0x3
+serdes_driver_current_lane2_xe8=0x2
+serdes_driver_current_lane3_xe8=0x2
+serdes_pre_driver_current_lane0_xe8=0x2
+serdes_pre_driver_current_lane1_xe8=0x3
+serdes_pre_driver_current_lane2_xe8=0x2
+serdes_pre_driver_current_lane3_xe8=0x2
+serdes_preemphasis_lane0_xe8=0xb270
+serdes_preemphasis_lane1_xe8=0xbb10
+serdes_preemphasis_lane2_xe8=0xb720
+serdes_preemphasis_lane3_xe8=0xb720
+
+# xe9 (40G)
+portmap_10=9:40
+xgxs_rx_lane_map_10=0x3120
+xgxs_tx_lane_map_10=0x3021
+phy_xaui_rx_polarity_flip_10=0x0
+phy_xaui_tx_polarity_flip_10=0x4
+serdes_driver_current_lane0_xe9=0x3
+serdes_driver_current_lane1_xe9=0x3
+serdes_driver_current_lane2_xe9=0x3
+serdes_driver_current_lane3_xe9=0x3
+serdes_pre_driver_current_lane0_xe9=0x3
+serdes_pre_driver_current_lane1_xe9=0x3
+serdes_pre_driver_current_lane2_xe9=0x3
+serdes_pre_driver_current_lane3_xe9=0x3
+serdes_preemphasis_lane0_xe9=0xc2f0
+serdes_preemphasis_lane1_xe9=0xc6e0
+serdes_preemphasis_lane2_xe9=0xbf00
+serdes_preemphasis_lane3_xe9=0xc2f0
+
+# xe10 (40G)
+portmap_11=17:40
+xgxs_rx_lane_map_11=0x213
+xgxs_tx_lane_map_11=0x132
+phy_xaui_rx_polarity_flip_11=0xe
+phy_xaui_tx_polarity_flip_11=0x0
+serdes_driver_current_lane0_xe10=0x2
+serdes_driver_current_lane1_xe10=0x2
+serdes_driver_current_lane2_xe10=0x2
+serdes_driver_current_lane3_xe10=0x2
+serdes_pre_driver_current_lane0_xe10=0x2
+serdes_pre_driver_current_lane1_xe10=0x2
+serdes_pre_driver_current_lane2_xe10=0x2
+serdes_pre_driver_current_lane3_xe10=0x2
+serdes_preemphasis_lane0_xe10=0xb330
+serdes_preemphasis_lane1_xe10=0xbb10
+serdes_preemphasis_lane2_xe10=0xbb10
+serdes_preemphasis_lane3_xe10=0xbb10
+
+# xe11 (40G)
+portmap_12=21:40
+xgxs_rx_lane_map_12=0x123
+xgxs_tx_lane_map_12=0x1203
+phy_xaui_rx_polarity_flip_12=0xc
+phy_xaui_tx_polarity_flip_12=0xe
+serdes_driver_current_lane0_xe11=0x2
+serdes_driver_current_lane1_xe11=0x2
+serdes_driver_current_lane2_xe11=0x2
+serdes_driver_current_lane3_xe11=0x2
+serdes_pre_driver_current_lane0_xe11=0x2
+serdes_pre_driver_current_lane1_xe11=0x2
+serdes_pre_driver_current_lane2_xe11=0x2
+serdes_pre_driver_current_lane3_xe11=0x2
+serdes_preemphasis_lane0_xe11=0xb330
+serdes_preemphasis_lane1_xe11=0xb330
+serdes_preemphasis_lane2_xe11=0xb330
+serdes_preemphasis_lane3_xe11=0xb330
+
+# xe12 (40G)
+portmap_13=53:40
+xgxs_rx_lane_map_13=0x213
+xgxs_tx_lane_map_13=0x231
+phy_xaui_rx_polarity_flip_13=0x1
+phy_xaui_tx_polarity_flip_13=0x0
+serdes_driver_current_lane0_xe12=0x2
+serdes_driver_current_lane1_xe12=0x2
+serdes_driver_current_lane2_xe12=0x2
+serdes_driver_current_lane3_xe12=0x2
+serdes_pre_driver_current_lane0_xe12=0x2
+serdes_pre_driver_current_lane1_xe12=0x2
+serdes_pre_driver_current_lane2_xe12=0x2
+serdes_pre_driver_current_lane3_xe12=0x2
+serdes_preemphasis_lane0_xe12=0xaf40
+serdes_preemphasis_lane1_xe12=0xaf40
+serdes_preemphasis_lane2_xe12=0xaf40
+serdes_preemphasis_lane3_xe12=0xaf40
+
+# xe13 (40G)
+portmap_14=49:40
+xgxs_rx_lane_map_14=0x1302
+xgxs_tx_lane_map_14=0x2031
+phy_xaui_rx_polarity_flip_14=0xb
+phy_xaui_tx_polarity_flip_14=0x3
+serdes_driver_current_lane0_xe13=0x2
+serdes_driver_current_lane1_xe13=0x2
+serdes_driver_current_lane2_xe13=0x2
+serdes_driver_current_lane3_xe13=0x2
+serdes_pre_driver_current_lane0_xe13=0x2
+serdes_pre_driver_current_lane1_xe13=0x2
+serdes_pre_driver_current_lane2_xe13=0x2
+serdes_pre_driver_current_lane3_xe13=0x2
+serdes_preemphasis_lane0_xe13=0xa760
+serdes_preemphasis_lane1_xe13=0xa760
+serdes_preemphasis_lane2_xe13=0xa760
+serdes_preemphasis_lane3_xe13=0xa760
+
+# xe14 (40G)
+portmap_15=57:40
+xgxs_rx_lane_map_15=0x213
+xgxs_tx_lane_map_15=0x2031
+phy_xaui_rx_polarity_flip_15=0x1
+phy_xaui_tx_polarity_flip_15=0x0
+serdes_driver_current_lane0_xe14=0x1
+serdes_driver_current_lane1_xe14=0x1
+serdes_driver_current_lane2_xe14=0x1
+serdes_driver_current_lane3_xe14=0x1
+serdes_pre_driver_current_lane0_xe14=0x1
+serdes_pre_driver_current_lane1_xe14=0x1
+serdes_pre_driver_current_lane2_xe14=0x1
+serdes_pre_driver_current_lane3_xe14=0x1
+serdes_preemphasis_lane0_xe14=0xa760
+serdes_preemphasis_lane1_xe14=0xa760
+serdes_preemphasis_lane2_xe14=0xa760
+serdes_preemphasis_lane3_xe14=0xa760
+
+# xe15 (40G)
+portmap_16=61:40
+xgxs_rx_lane_map_16=0x132
+xgxs_tx_lane_map_16=0x213
+phy_xaui_rx_polarity_flip_16=0x0
+phy_xaui_tx_polarity_flip_16=0x0
+serdes_driver_current_lane0_xe15=0x2
+serdes_driver_current_lane1_xe15=0x2
+serdes_driver_current_lane2_xe15=0x2
+serdes_driver_current_lane3_xe15=0x2
+serdes_pre_driver_current_lane0_xe15=0x2
+serdes_pre_driver_current_lane1_xe15=0x2
+serdes_pre_driver_current_lane2_xe15=0x2
+serdes_pre_driver_current_lane3_xe15=0x2
+serdes_preemphasis_lane0_xe15=0xa760
+serdes_preemphasis_lane1_xe15=0xa760
+serdes_preemphasis_lane2_xe15=0xa760
+serdes_preemphasis_lane3_xe15=0xa760
+
+# xe16 (40G)
+portmap_17=69:40
+xgxs_rx_lane_map_17=0x213
+xgxs_tx_lane_map_17=0x2130
+phy_xaui_rx_polarity_flip_17=0x1
+phy_xaui_tx_polarity_flip_17=0xf
+serdes_driver_current_lane0_xe16=0x1
+serdes_driver_current_lane1_xe16=0x1
+serdes_driver_current_lane2_xe16=0x1
+serdes_driver_current_lane3_xe16=0x1
+serdes_pre_driver_current_lane0_xe16=0x1
+serdes_pre_driver_current_lane1_xe16=0x1
+serdes_pre_driver_current_lane2_xe16=0x1
+serdes_pre_driver_current_lane3_xe16=0x1
+serdes_preemphasis_lane0_xe16=0xa760
+serdes_preemphasis_lane1_xe16=0xa760
+serdes_preemphasis_lane2_xe16=0xa760
+serdes_preemphasis_lane3_xe16=0xa760
+
+# xe17 (40G)
+portmap_18=65:40
+xgxs_rx_lane_map_18=0x132
+xgxs_tx_lane_map_18=0x2031
+phy_xaui_rx_polarity_flip_18=0x3
+phy_xaui_tx_polarity_flip_18=0x9
+serdes_driver_current_lane0_xe17=0x1
+serdes_driver_current_lane1_xe17=0x1
+serdes_driver_current_lane2_xe17=0x1
+serdes_driver_current_lane3_xe17=0x1
+serdes_pre_driver_current_lane0_xe17=0x1
+serdes_pre_driver_current_lane1_xe17=0x1
+serdes_pre_driver_current_lane2_xe17=0x1
+serdes_pre_driver_current_lane3_xe17=0x1
+serdes_preemphasis_lane0_xe17=0xa370
+serdes_preemphasis_lane1_xe17=0xa370
+serdes_preemphasis_lane2_xe17=0xa370
+serdes_preemphasis_lane3_xe17=0xa370
+
+# xe18 (40G)
+portmap_19=73:40
+xgxs_rx_lane_map_19=0x213
+xgxs_tx_lane_map_19=0x2031
+phy_xaui_rx_polarity_flip_19=0x1
+phy_xaui_tx_polarity_flip_19=0x0
+serdes_driver_current_lane0_xe18=0x2
+serdes_driver_current_lane1_xe18=0x2
+serdes_driver_current_lane2_xe18=0x2
+serdes_driver_current_lane3_xe18=0x2
+serdes_pre_driver_current_lane0_xe18=0x2
+serdes_pre_driver_current_lane1_xe18=0x2
+serdes_pre_driver_current_lane2_xe18=0x2
+serdes_pre_driver_current_lane3_xe18=0x2
+serdes_preemphasis_lane0_xe18=0xa760
+serdes_preemphasis_lane1_xe18=0xa760
+serdes_preemphasis_lane2_xe18=0xa760
+serdes_preemphasis_lane3_xe18=0xa760
+
+# xe19 (40G)
+portmap_20=77:40
+xgxs_rx_lane_map_20=0x123
+xgxs_tx_lane_map_20=0x1203
+phy_xaui_rx_polarity_flip_20=0x3
+phy_xaui_tx_polarity_flip_20=0xe
+serdes_driver_current_lane0_xe19=0x2
+serdes_driver_current_lane1_xe19=0x2
+serdes_driver_current_lane2_xe19=0x2
+serdes_driver_current_lane3_xe19=0x2
+serdes_pre_driver_current_lane0_xe19=0x2
+serdes_pre_driver_current_lane1_xe19=0x2
+serdes_pre_driver_current_lane2_xe19=0x2
+serdes_pre_driver_current_lane3_xe19=0x2
+serdes_preemphasis_lane0_xe19=0xaf40
+serdes_preemphasis_lane1_xe19=0xaf40
+serdes_preemphasis_lane2_xe19=0xaf40
+serdes_preemphasis_lane3_xe19=0xaf40
+
+# xe20 (40G)
+portmap_21=109:40
+xgxs_rx_lane_map_21=0x132
+xgxs_tx_lane_map_21=0x132
+phy_xaui_rx_polarity_flip_21=0x8
+phy_xaui_tx_polarity_flip_21=0x0
+serdes_driver_current_lane0_xe20=0x1
+serdes_driver_current_lane1_xe20=0x1
+serdes_driver_current_lane2_xe20=0x1
+serdes_driver_current_lane3_xe20=0x2
+serdes_pre_driver_current_lane0_xe20=0x1
+serdes_pre_driver_current_lane1_xe20=0x1
+serdes_pre_driver_current_lane2_xe20=0x1
+serdes_pre_driver_current_lane3_xe20=0x2
+serdes_preemphasis_lane0_xe20=0xb330
+serdes_preemphasis_lane1_xe20=0xb330
+serdes_preemphasis_lane2_xe20=0xb330
+serdes_preemphasis_lane3_xe20=0xbff0
+
+# xe21 (40G)
+portmap_22=105:40
+xgxs_rx_lane_map_22=0x1320
+xgxs_tx_lane_map_22=0x3021
+phy_xaui_rx_polarity_flip_22=0xd
+phy_xaui_tx_polarity_flip_22=0xb
+serdes_driver_current_lane0_xe21=0x1
+serdes_driver_current_lane1_xe21=0x1
+serdes_driver_current_lane2_xe21=0x1
+serdes_driver_current_lane3_xe21=0x1
+serdes_pre_driver_current_lane0_xe21=0x1
+serdes_pre_driver_current_lane1_xe21=0x1
+serdes_pre_driver_current_lane2_xe21=0x1
+serdes_pre_driver_current_lane3_xe21=0x1
+serdes_preemphasis_lane0_xe21=0xb330
+serdes_preemphasis_lane1_xe21=0xb330
+serdes_preemphasis_lane2_xe21=0xb330
+serdes_preemphasis_lane3_xe21=0xb330
+
+# xe22 (40G)
+portmap_23=113:40
+xgxs_rx_lane_map_23=0x132
+xgxs_tx_lane_map_23=0x132
+phy_xaui_rx_polarity_flip_23=0x8
+phy_xaui_tx_polarity_flip_23=0x0
+serdes_driver_current_lane0_xe22=0x1
+serdes_driver_current_lane1_xe22=0x1
+serdes_driver_current_lane2_xe22=0x1
+serdes_driver_current_lane3_xe22=0x1
+serdes_pre_driver_current_lane0_xe22=0x1
+serdes_pre_driver_current_lane1_xe22=0x1
+serdes_pre_driver_current_lane2_xe22=0x1
+serdes_pre_driver_current_lane3_xe22=0x1
+serdes_preemphasis_lane0_xe22=0xbb10
+serdes_preemphasis_lane1_xe22=0xbb10
+serdes_preemphasis_lane2_xe22=0xbb10
+serdes_preemphasis_lane3_xe22=0xc2f0
+
+# xe23 (40G)
+portmap_24=117:40
+xgxs_rx_lane_map_24=0x231
+xgxs_tx_lane_map_24=0x1203
+phy_xaui_rx_polarity_flip_24=0x3
+phy_xaui_tx_polarity_flip_24=0xe
+serdes_driver_current_lane0_xe23=0x3
+serdes_driver_current_lane1_xe23=0x5
+serdes_driver_current_lane2_xe23=0x3
+serdes_driver_current_lane3_xe23=0x3
+serdes_pre_driver_current_lane0_xe23=0x3
+serdes_pre_driver_current_lane1_xe23=0x5
+serdes_pre_driver_current_lane2_xe23=0x3
+serdes_pre_driver_current_lane3_xe23=0x3
+serdes_preemphasis_lane0_xe23=0xc6e0
+serdes_preemphasis_lane1_xe23=0xc6e0
+serdes_preemphasis_lane2_xe23=0xc6e0
+serdes_preemphasis_lane3_xe23=0xc6e0
+
+# xe24 (40G)
+portmap_25=125:40
+xgxs_rx_lane_map_25=0x132
+xgxs_tx_lane_map_25=0x132
+phy_xaui_rx_polarity_flip_25=0x8
+phy_xaui_tx_polarity_flip_25=0x0
+serdes_driver_current_lane0_xe24=0x4
+serdes_driver_current_lane1_xe24=0x4
+serdes_driver_current_lane2_xe24=0x4
+serdes_driver_current_lane3_xe24=0x4
+serdes_pre_driver_current_lane0_xe24=0x4
+serdes_pre_driver_current_lane1_xe24=0x4
+serdes_pre_driver_current_lane2_xe24=0x4
+serdes_pre_driver_current_lane3_xe24=0x4
+serdes_preemphasis_lane0_xe24=0xc6e0
+serdes_preemphasis_lane1_xe24=0xc6e0
+serdes_preemphasis_lane2_xe24=0xc6e0
+serdes_preemphasis_lane3_xe24=0xcec0
+
+# xe25 (40G)
+portmap_26=121:40
+xgxs_rx_lane_map_26=0x1320
+xgxs_tx_lane_map_26=0x3021
+phy_xaui_rx_polarity_flip_26=0xd
+phy_xaui_tx_polarity_flip_26=0xb
+serdes_driver_current_lane0_xe25=0x4
+serdes_driver_current_lane1_xe25=0x4
+serdes_driver_current_lane2_xe25=0x4
+serdes_driver_current_lane3_xe25=0x4
+serdes_pre_driver_current_lane0_xe25=0x4
+serdes_pre_driver_current_lane1_xe25=0x4
+serdes_pre_driver_current_lane2_xe25=0x4
+serdes_pre_driver_current_lane3_xe25=0x4
+serdes_preemphasis_lane0_xe25=0xc6e0
+serdes_preemphasis_lane1_xe25=0xc6e0
+serdes_preemphasis_lane2_xe25=0xc6e0
+serdes_preemphasis_lane3_xe25=0xc6e0
+
+# xe26 (40G)
+portmap_27=81:40
+xgxs_rx_lane_map_27=0x1320
+xgxs_tx_lane_map_27=0x2031
+phy_xaui_rx_polarity_flip_27=0x1
+phy_xaui_tx_polarity_flip_27=0x2
+serdes_driver_current_lane0_xe26=0x2
+serdes_driver_current_lane1_xe26=0x2
+serdes_driver_current_lane2_xe26=0x2
+serdes_driver_current_lane3_xe26=0x2
+serdes_pre_driver_current_lane0_xe26=0x2
+serdes_pre_driver_current_lane1_xe26=0x2
+serdes_pre_driver_current_lane2_xe26=0x2
+serdes_pre_driver_current_lane3_xe26=0x2
+serdes_preemphasis_lane0_xe26=0xbb10
+serdes_preemphasis_lane1_xe26=0xbb10
+serdes_preemphasis_lane2_xe26=0xbf00
+serdes_preemphasis_lane3_xe26=0xbb10
+
+# xe27 (40G)
+portmap_28=85:40
+xgxs_rx_lane_map_28=0x213
+xgxs_tx_lane_map_28=0x1203
+phy_xaui_rx_polarity_flip_28=0xc
+phy_xaui_tx_polarity_flip_28=0xe
+serdes_driver_current_lane0_xe27=0x4
+serdes_driver_current_lane1_xe27=0x5
+serdes_driver_current_lane2_xe27=0x4
+serdes_driver_current_lane3_xe27=0x5
+serdes_pre_driver_current_lane0_xe27=0x4
+serdes_pre_driver_current_lane1_xe27=0x5
+serdes_pre_driver_current_lane2_xe27=0x4
+serdes_pre_driver_current_lane3_xe27=0x5
+serdes_preemphasis_lane0_xe27=0xc2f0
+serdes_preemphasis_lane1_xe27=0xc6e0
+serdes_preemphasis_lane2_xe27=0xc6e0
+serdes_preemphasis_lane3_xe27=0xc6e0
+
+# xe28 (40G)
+portmap_29=93:40
+xgxs_rx_lane_map_29=0x1320
+xgxs_tx_lane_map_29=0x2031
+phy_xaui_rx_polarity_flip_29=0x1
+phy_xaui_tx_polarity_flip_29=0x2
+serdes_driver_current_lane0_xe28=0x4
+serdes_driver_current_lane1_xe28=0x4
+serdes_driver_current_lane2_xe28=0x4
+serdes_driver_current_lane3_xe28=0x4
+serdes_pre_driver_current_lane0_xe28=0x4
+serdes_pre_driver_current_lane1_xe28=0x4
+serdes_pre_driver_current_lane2_xe28=0x4
+serdes_pre_driver_current_lane3_xe28=0x4
+serdes_preemphasis_lane0_xe28=0xc2f0
+serdes_preemphasis_lane1_xe28=0xc2f0
+serdes_preemphasis_lane2_xe28=0xc2f0
+serdes_preemphasis_lane3_xe28=0xc2f0
+
+# xe29 (40G)
+portmap_30=89:40
+xgxs_rx_lane_map_30=0x1320
+xgxs_tx_lane_map_30=0x3021
+phy_xaui_rx_polarity_flip_30=0x2
+phy_xaui_tx_polarity_flip_30=0xb
+serdes_driver_current_lane0_xe29=0x4
+serdes_driver_current_lane1_xe29=0x4
+serdes_driver_current_lane2_xe29=0x4
+serdes_driver_current_lane3_xe29=0x4
+serdes_pre_driver_current_lane0_xe29=0x4
+serdes_pre_driver_current_lane1_xe29=0x4
+serdes_pre_driver_current_lane2_xe29=0x4
+serdes_pre_driver_current_lane3_xe29=0x4
+serdes_preemphasis_lane0_xe29=0xcad0
+serdes_preemphasis_lane1_xe29=0xc6e0
+serdes_preemphasis_lane2_xe29=0xc6e0
+serdes_preemphasis_lane3_xe29=0xc6e0
+
+# xe30 (40G)
+portmap_31=101:40
+xgxs_rx_lane_map_31=0x1320
+xgxs_tx_lane_map_31=0x1203
+phy_xaui_rx_polarity_flip_31=0x1
+phy_xaui_tx_polarity_flip_31=0x6
+serdes_driver_current_lane0_xe30=0x6
+serdes_driver_current_lane1_xe30=0x6
+serdes_driver_current_lane2_xe30=0x6
+serdes_driver_current_lane3_xe30=0x7
+serdes_pre_driver_current_lane0_xe30=0x6
+serdes_pre_driver_current_lane1_xe30=0x6
+serdes_pre_driver_current_lane2_xe30=0x6
+serdes_pre_driver_current_lane3_xe30=0x7
+serdes_preemphasis_lane0_xe30=0xcec0
+serdes_preemphasis_lane1_xe30=0xcec0
+serdes_preemphasis_lane2_xe30=0xcad0
+serdes_preemphasis_lane3_xe30=0xc6e0
+
+# xe31 (40G)
+portmap_32=97:40
+xgxs_rx_lane_map_32=0x213
+xgxs_tx_lane_map_32=0x2031
+phy_xaui_rx_polarity_flip_32=0xc
+phy_xaui_tx_polarity_flip_32=0x3
+serdes_driver_current_lane0_xe31=0x5
+serdes_driver_current_lane1_xe31=0x5
+serdes_driver_current_lane2_xe31=0x5
+serdes_driver_current_lane3_xe31=0x5
+serdes_pre_driver_current_lane0_xe31=0x5
+serdes_pre_driver_current_lane1_xe31=0x5
+serdes_pre_driver_current_lane2_xe31=0x5
+serdes_pre_driver_current_lane3_xe31=0x5
+serdes_preemphasis_lane0_xe31=0xcad0
+serdes_preemphasis_lane1_xe31=0xcad0
+serdes_preemphasis_lane2_xe31=0xcad0
+serdes_preemphasis_lane3_xe31=0xcad0
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/buffers.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/buffers.json.j2
new file mode 100644
index 000000000000..b67cf577ab75
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/buffers.json.j2
@@ -0,0 +1,3 @@
+{%- set default_topo = 't1' %}
+{%- include 'buffers_config.j2' %}
+
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/buffers_defaults_def.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/buffers_defaults_def.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/buffers_defaults_def.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/buffers_defaults_t0.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/buffers_defaults_t0.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/buffers_defaults_t0.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/buffers_defaults_t1.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/buffers_defaults_t1.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/buffers_defaults_t1.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/lanemap.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/lanemap.ini
new file mode 100644
index 000000000000..36278a01778c
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/lanemap.ini
@@ -0,0 +1,32 @@
+eth1:25,26,27,28
+eth2:29,30,31,32
+eth3:33,34,35,36
+eth4:37,38,39,40
+eth5:45,46,47,48
+eth6:41,42,43,44
+eth7:1,2,3,4
+eth8:5,6,7,8
+eth9:13,14,15,16
+eth10:9,10,11,12
+eth11:17,18,19,20
+eth12:21,22,23,24
+eth13:53,54,55,56
+eth14:49,50,51,52
+eth15:57,58,59,60
+eth16:61,62,63,64
+eth17:69,70,71,72
+eth18:65,66,67,68
+eth19:73,74,75,76
+eth20:77,78,79,80
+eth21:109,110,111,112
+eth22:105,106,107,108
+eth23:113,114,115,116
+eth24:117,118,119,120
+eth25:125,126,127,128
+eth26:121,122,123,124
+eth27:81,82,83,84
+eth28:85,86,87,88
+eth29:93,94,95,96
+eth30:89,90,91,92
+eth31:101,102,103,104
+eth32:97,98,99,100
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/pg_profile_lookup.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/pg_profile_lookup.ini
new file mode 100644
index 000000000000..9f2eacb6fc42
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/pg_profile_lookup.ini
@@ -0,0 +1,17 @@
+# PG lossless profiles.
+# speed cable size xon xoff threshold xon_offset
+ 10000 5m 56368 18432 55120 -3 2496
+ 25000 5m 56368 18432 55120 -3 2496
+ 40000 5m 56368 18432 55120 -3 2496
+ 50000 5m 56368 18432 55120 -3 2496
+ 100000 5m 56368 18432 55120 -3 2496
+ 10000 40m 56368 18432 55120 -3 2496
+ 25000 40m 56368 18432 55120 -3 2496
+ 40000 40m 56368 18432 55120 -3 2496
+ 50000 40m 56368 18432 55120 -3 2496
+ 100000 40m 56368 18432 55120 -3 2496
+ 10000 300m 56368 18432 55120 -3 2496
+ 25000 300m 56368 18432 55120 -3 2496
+ 40000 300m 56368 18432 55120 -3 2496
+ 50000 300m 56368 18432 55120 -3 2496
+ 100000 300m 56368 18432 55120 -3 2496
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/port_config.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/port_config.ini
new file mode 100644
index 000000000000..95cf5eec9e4e
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/port_config.ini
@@ -0,0 +1,33 @@
+# name lanes alias index speed
+Ethernet0 25,26,27,28 fortyGigE0/0 0 40000
+Ethernet4 29,30,31,32 fortyGigE0/4 1 40000
+Ethernet8 33,34,35,36 fortyGigE0/8 2 40000
+Ethernet12 37,38,39,40 fortyGigE0/12 3 40000
+Ethernet16 45,46,47,48 fortyGigE0/16 4 40000
+Ethernet20 41,42,43,44 fortyGigE0/20 5 40000
+Ethernet24 1,2,3,4 fortyGigE0/24 6 40000
+Ethernet28 5,6,7,8 fortyGigE0/28 7 40000
+Ethernet32 13,14,15,16 fortyGigE0/32 8 40000
+Ethernet36 9,10,11,12 fortyGigE0/36 9 40000
+Ethernet40 17,18,19,20 fortyGigE0/40 10 40000
+Ethernet44 21,22,23,24 fortyGigE0/44 11 40000
+Ethernet48 53,54,55,56 fortyGigE0/48 12 40000
+Ethernet52 49,50,51,52 fortyGigE0/52 13 40000
+Ethernet56 57,58,59,60 fortyGigE0/56 14 40000
+Ethernet60 61,62,63,64 fortyGigE0/60 15 40000
+Ethernet64 69,70,71,72 fortyGigE0/64 16 40000
+Ethernet68 65,66,67,68 fortyGigE0/68 17 40000
+Ethernet72 73,74,75,76 fortyGigE0/72 18 40000
+Ethernet76 77,78,79,80 fortyGigE0/76 19 40000
+Ethernet80 109,110,111,112 fortyGigE0/80 20 40000
+Ethernet84 105,106,107,108 fortyGigE0/84 21 40000
+Ethernet88 113,114,115,116 fortyGigE0/88 22 40000
+Ethernet92 117,118,119,120 fortyGigE0/92 23 40000
+Ethernet96 125,126,127,128 fortyGigE0/96 24 40000
+Ethernet100 121,122,123,124 fortyGigE0/100 25 40000
+Ethernet104 81,82,83,84 fortyGigE0/104 26 40000
+Ethernet108 85,86,87,88 fortyGigE0/108 27 40000
+Ethernet112 93,94,95,96 fortyGigE0/112 28 40000
+Ethernet116 89,90,91,92 fortyGigE0/116 29 40000
+Ethernet120 101,102,103,104 fortyGigE0/120 30 40000
+Ethernet124 97,98,99,100 fortyGigE0/124 31 40000
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/qos.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/qos.json.j2
new file mode 100644
index 000000000000..3e548325ea30
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/qos.json.j2
@@ -0,0 +1 @@
+{%- include 'qos_config.j2' %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/sai.profile b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/sai.profile
new file mode 100644
index 000000000000..bfc466f27e54
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/sai.profile
@@ -0,0 +1,5 @@
+SAI_WARM_BOOT_READ_FILE=/var/cache/sai_warmboot.bin
+SAI_WARM_BOOT_WRITE_FILE=/var/cache/sai_warmboot.bin
+SAI_VS_SWITCH_TYPE=SAI_VS_SWITCH_TYPE_BCM56850
+SAI_VS_HOSTIF_USE_TAP_DEVICE=true
+SAI_VS_INTERFACE_LANE_MAP_FILE=/usr/share/sonic/hwsku/lanemap.ini
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/td2-s6000-32x40G.config.bcm b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/td2-s6000-32x40G.config.bcm
new file mode 100644
index 000000000000..4c94db7107c7
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/td2-s6000-32x40G.config.bcm
@@ -0,0 +1,646 @@
+# Old LPM only configuration
+# l2_mem_entries=163840
+# l3_mem_entries=90112
+# l3_alpm_enable=0
+# ipv6_lpm_128b_enable=0
+#
+# ALPM enable
+l3_alpm_enable=2
+ipv6_lpm_128b_enable=1
+l2_mem_entries=32768
+l3_mem_entries=16384
+
+# From old config file
+os=unix
+higig2_hdr_mode=1
+
+# Parity
+parity_correction=1
+parity_enable=1
+stat_if_parity_enable=0
+
+#
+bcm_num_cos=8
+bcm_stat_interval=2000000
+l2xmsg_hostbuf_size=8192
+l2xmsg_mode=1
+lls_num_l2uc=12
+max_vp_lags=0
+miim_intr_enable=0
+mmu_lossless=0
+module_64ports=0
+schan_intr_enable=0
+stable_size=0x2000000
+tdma_timeout_usec=5000000
+
+pbmp_oversubscribe=0x000007fffffffffffffffffffffffffe
+pbmp_xport_xe=0x000007fffffffffffffffffffffffffe
+
+# Ports configuration
+# xe0 (40G)
+portmap_1=25:40
+xgxs_rx_lane_map_1=0x213
+xgxs_tx_lane_map_1=0x2031
+phy_xaui_rx_polarity_flip_1=0xe
+phy_xaui_tx_polarity_flip_1=0x2
+serdes_driver_current_lane0_xe0=0x5
+serdes_driver_current_lane1_xe0=0x5
+serdes_driver_current_lane2_xe0=0x5
+serdes_driver_current_lane3_xe0=0x5
+serdes_pre_driver_current_lane0_xe0=0x5
+serdes_pre_driver_current_lane1_xe0=0x5
+serdes_pre_driver_current_lane2_xe0=0x5
+serdes_pre_driver_current_lane3_xe0=0x5
+serdes_preemphasis_lane0_xe0=0xcad0
+serdes_preemphasis_lane1_xe0=0xc6e0
+serdes_preemphasis_lane2_xe0=0xc6e0
+serdes_preemphasis_lane3_xe0=0xd2b0
+
+# xe1 (40G)
+portmap_2=29:40
+xgxs_rx_lane_map_2=0x213
+xgxs_tx_lane_map_2=0x213
+phy_xaui_rx_polarity_flip_2=0xc
+phy_xaui_tx_polarity_flip_2=0x9
+serdes_driver_current_lane0_xe1=0x6
+serdes_driver_current_lane1_xe1=0x7
+serdes_driver_current_lane2_xe1=0x6
+serdes_driver_current_lane3_xe1=0x6
+serdes_pre_driver_current_lane0_xe1=0x6
+serdes_pre_driver_current_lane1_xe1=0x7
+serdes_pre_driver_current_lane2_xe1=0x6
+serdes_pre_driver_current_lane3_xe1=0x6
+serdes_preemphasis_lane0_xe1=0xc2f0
+serdes_preemphasis_lane1_xe1=0xd2b0
+serdes_preemphasis_lane2_xe1=0xc6e0
+serdes_preemphasis_lane3_xe1=0xc2f0
+
+# xe2 (40G)
+portmap_3=33:40
+xgxs_rx_lane_map_3=0x213
+xgxs_tx_lane_map_3=0x132
+phy_xaui_rx_polarity_flip_3=0xe
+phy_xaui_tx_polarity_flip_3=0x2
+serdes_driver_current_lane0_xe2=0x4
+serdes_driver_current_lane1_xe2=0x4
+serdes_driver_current_lane2_xe2=0x4
+serdes_driver_current_lane3_xe2=0x4
+serdes_pre_driver_current_lane0_xe2=0x4
+serdes_pre_driver_current_lane1_xe2=0x4
+serdes_pre_driver_current_lane2_xe2=0x4
+serdes_pre_driver_current_lane3_xe2=0x4
+serdes_preemphasis_lane0_xe2=0xc6e0
+serdes_preemphasis_lane1_xe2=0xc6e0
+serdes_preemphasis_lane2_xe2=0xc6e0
+serdes_preemphasis_lane3_xe2=0xc6e0
+
+# xe3 (40G)
+portmap_4=37:40
+xgxs_rx_lane_map_4=0x213
+xgxs_tx_lane_map_4=0x1203
+phy_xaui_rx_polarity_flip_4=0x3
+phy_xaui_tx_polarity_flip_4=0xe
+serdes_driver_current_lane0_xe3=0x4
+serdes_driver_current_lane1_xe3=0x4
+serdes_driver_current_lane2_xe3=0x4
+serdes_driver_current_lane3_xe3=0x4
+serdes_pre_driver_current_lane0_xe3=0x4
+serdes_pre_driver_current_lane1_xe3=0x4
+serdes_pre_driver_current_lane2_xe3=0x4
+serdes_pre_driver_current_lane3_xe3=0x4
+serdes_preemphasis_lane0_xe3=0xcad0
+serdes_preemphasis_lane1_xe3=0xcad0
+serdes_preemphasis_lane2_xe3=0xc2f0
+serdes_preemphasis_lane3_xe3=0xc2f0
+
+# xe4 (40G)
+portmap_5=45:40
+xgxs_rx_lane_map_5=0x213
+xgxs_tx_lane_map_5=0x213
+phy_xaui_rx_polarity_flip_5=0xe
+phy_xaui_tx_polarity_flip_5=0x8
+serdes_driver_current_lane0_xe4=0x4
+serdes_driver_current_lane1_xe4=0x4
+serdes_driver_current_lane2_xe4=0x4
+serdes_driver_current_lane3_xe4=0x4
+serdes_pre_driver_current_lane0_xe4=0x4
+serdes_pre_driver_current_lane1_xe4=0x4
+serdes_pre_driver_current_lane2_xe4=0x4
+serdes_pre_driver_current_lane3_xe4=0x4
+serdes_preemphasis_lane0_xe4=0xc2f0
+serdes_preemphasis_lane1_xe4=0xc2f0
+serdes_preemphasis_lane2_xe4=0xc2f0
+serdes_preemphasis_lane3_xe4=0xc2f0
+
+# xe5 (40G)
+portmap_6=41:40
+xgxs_rx_lane_map_6=0x213
+xgxs_tx_lane_map_6=0x3021
+phy_xaui_rx_polarity_flip_6=0x3
+phy_xaui_tx_polarity_flip_6=0xb
+serdes_driver_current_lane0_xe5=0x4
+serdes_driver_current_lane1_xe5=0x4
+serdes_driver_current_lane2_xe5=0x4
+serdes_driver_current_lane3_xe5=0x4
+serdes_pre_driver_current_lane0_xe5=0x4
+serdes_pre_driver_current_lane1_xe5=0x4
+serdes_pre_driver_current_lane2_xe5=0x4
+serdes_pre_driver_current_lane3_xe5=0x4
+serdes_preemphasis_lane0_xe5=0xc6e0
+serdes_preemphasis_lane1_xe5=0xc2f0
+serdes_preemphasis_lane2_xe5=0xc2f0
+serdes_preemphasis_lane3_xe5=0xcad0
+
+# xe6 (40G)
+portmap_7=1:40
+xgxs_rx_lane_map_7=0x213
+xgxs_tx_lane_map_7=0x2031
+phy_xaui_rx_polarity_flip_7=0xe
+phy_xaui_tx_polarity_flip_7=0xd
+serdes_driver_current_lane0_xe6=0x5
+serdes_driver_current_lane1_xe6=0x5
+serdes_driver_current_lane2_xe6=0x5
+serdes_driver_current_lane3_xe6=0x5
+serdes_pre_driver_current_lane0_xe6=0x5
+serdes_pre_driver_current_lane1_xe6=0x5
+serdes_pre_driver_current_lane2_xe6=0x5
+serdes_pre_driver_current_lane3_xe6=0x5
+serdes_preemphasis_lane0_xe6=0xc6e0
+serdes_preemphasis_lane1_xe6=0xcad0
+serdes_preemphasis_lane2_xe6=0xc6e0
+serdes_preemphasis_lane3_xe6=0xcad0
+
+# xe7 (40G)
+portmap_8=5:40
+xgxs_rx_lane_map_8=0x213
+xgxs_tx_lane_map_8=0x1203
+phy_xaui_rx_polarity_flip_8=0xc
+phy_xaui_tx_polarity_flip_8=0x1
+serdes_driver_current_lane0_xe7=0x4
+serdes_driver_current_lane1_xe7=0x4
+serdes_driver_current_lane2_xe7=0x4
+serdes_driver_current_lane3_xe7=0x4
+serdes_pre_driver_current_lane0_xe7=0x4
+serdes_pre_driver_current_lane1_xe7=0x4
+serdes_pre_driver_current_lane2_xe7=0x4
+serdes_pre_driver_current_lane3_xe7=0x4
+serdes_preemphasis_lane0_xe7=0xc6e0
+serdes_preemphasis_lane1_xe7=0xc6e0
+serdes_preemphasis_lane2_xe7=0xc6e0
+serdes_preemphasis_lane3_xe7=0xc6e0
+
+# xe8 (40G)
+portmap_9=13:40
+xgxs_rx_lane_map_9=0x213
+xgxs_tx_lane_map_9=0x132
+phy_xaui_rx_polarity_flip_9=0xe
+phy_xaui_tx_polarity_flip_9=0x0
+serdes_driver_current_lane0_xe8=0x2
+serdes_driver_current_lane1_xe8=0x3
+serdes_driver_current_lane2_xe8=0x2
+serdes_driver_current_lane3_xe8=0x2
+serdes_pre_driver_current_lane0_xe8=0x2
+serdes_pre_driver_current_lane1_xe8=0x3
+serdes_pre_driver_current_lane2_xe8=0x2
+serdes_pre_driver_current_lane3_xe8=0x2
+serdes_preemphasis_lane0_xe8=0xb270
+serdes_preemphasis_lane1_xe8=0xbb10
+serdes_preemphasis_lane2_xe8=0xb720
+serdes_preemphasis_lane3_xe8=0xb720
+
+# xe9 (40G)
+portmap_10=9:40
+xgxs_rx_lane_map_10=0x3120
+xgxs_tx_lane_map_10=0x3021
+phy_xaui_rx_polarity_flip_10=0x0
+phy_xaui_tx_polarity_flip_10=0x4
+serdes_driver_current_lane0_xe9=0x3
+serdes_driver_current_lane1_xe9=0x3
+serdes_driver_current_lane2_xe9=0x3
+serdes_driver_current_lane3_xe9=0x3
+serdes_pre_driver_current_lane0_xe9=0x3
+serdes_pre_driver_current_lane1_xe9=0x3
+serdes_pre_driver_current_lane2_xe9=0x3
+serdes_pre_driver_current_lane3_xe9=0x3
+serdes_preemphasis_lane0_xe9=0xc2f0
+serdes_preemphasis_lane1_xe9=0xc6e0
+serdes_preemphasis_lane2_xe9=0xbf00
+serdes_preemphasis_lane3_xe9=0xc2f0
+
+# xe10 (40G)
+portmap_11=17:40
+xgxs_rx_lane_map_11=0x213
+xgxs_tx_lane_map_11=0x132
+phy_xaui_rx_polarity_flip_11=0xe
+phy_xaui_tx_polarity_flip_11=0x0
+serdes_driver_current_lane0_xe10=0x2
+serdes_driver_current_lane1_xe10=0x2
+serdes_driver_current_lane2_xe10=0x2
+serdes_driver_current_lane3_xe10=0x2
+serdes_pre_driver_current_lane0_xe10=0x2
+serdes_pre_driver_current_lane1_xe10=0x2
+serdes_pre_driver_current_lane2_xe10=0x2
+serdes_pre_driver_current_lane3_xe10=0x2
+serdes_preemphasis_lane0_xe10=0xb330
+serdes_preemphasis_lane1_xe10=0xbb10
+serdes_preemphasis_lane2_xe10=0xbb10
+serdes_preemphasis_lane3_xe10=0xbb10
+
+# xe11 (40G)
+portmap_12=21:40
+xgxs_rx_lane_map_12=0x123
+xgxs_tx_lane_map_12=0x1203
+phy_xaui_rx_polarity_flip_12=0xc
+phy_xaui_tx_polarity_flip_12=0xe
+serdes_driver_current_lane0_xe11=0x2
+serdes_driver_current_lane1_xe11=0x2
+serdes_driver_current_lane2_xe11=0x2
+serdes_driver_current_lane3_xe11=0x2
+serdes_pre_driver_current_lane0_xe11=0x2
+serdes_pre_driver_current_lane1_xe11=0x2
+serdes_pre_driver_current_lane2_xe11=0x2
+serdes_pre_driver_current_lane3_xe11=0x2
+serdes_preemphasis_lane0_xe11=0xb330
+serdes_preemphasis_lane1_xe11=0xb330
+serdes_preemphasis_lane2_xe11=0xb330
+serdes_preemphasis_lane3_xe11=0xb330
+
+# xe12 (40G)
+portmap_13=53:40
+xgxs_rx_lane_map_13=0x213
+xgxs_tx_lane_map_13=0x231
+phy_xaui_rx_polarity_flip_13=0x1
+phy_xaui_tx_polarity_flip_13=0x0
+serdes_driver_current_lane0_xe12=0x2
+serdes_driver_current_lane1_xe12=0x2
+serdes_driver_current_lane2_xe12=0x2
+serdes_driver_current_lane3_xe12=0x2
+serdes_pre_driver_current_lane0_xe12=0x2
+serdes_pre_driver_current_lane1_xe12=0x2
+serdes_pre_driver_current_lane2_xe12=0x2
+serdes_pre_driver_current_lane3_xe12=0x2
+serdes_preemphasis_lane0_xe12=0xaf40
+serdes_preemphasis_lane1_xe12=0xaf40
+serdes_preemphasis_lane2_xe12=0xaf40
+serdes_preemphasis_lane3_xe12=0xaf40
+
+# xe13 (40G)
+portmap_14=49:40
+xgxs_rx_lane_map_14=0x1302
+xgxs_tx_lane_map_14=0x2031
+phy_xaui_rx_polarity_flip_14=0xb
+phy_xaui_tx_polarity_flip_14=0x3
+serdes_driver_current_lane0_xe13=0x2
+serdes_driver_current_lane1_xe13=0x2
+serdes_driver_current_lane2_xe13=0x2
+serdes_driver_current_lane3_xe13=0x2
+serdes_pre_driver_current_lane0_xe13=0x2
+serdes_pre_driver_current_lane1_xe13=0x2
+serdes_pre_driver_current_lane2_xe13=0x2
+serdes_pre_driver_current_lane3_xe13=0x2
+serdes_preemphasis_lane0_xe13=0xa760
+serdes_preemphasis_lane1_xe13=0xa760
+serdes_preemphasis_lane2_xe13=0xa760
+serdes_preemphasis_lane3_xe13=0xa760
+
+# xe14 (40G)
+portmap_15=57:40
+xgxs_rx_lane_map_15=0x213
+xgxs_tx_lane_map_15=0x2031
+phy_xaui_rx_polarity_flip_15=0x1
+phy_xaui_tx_polarity_flip_15=0x0
+serdes_driver_current_lane0_xe14=0x1
+serdes_driver_current_lane1_xe14=0x1
+serdes_driver_current_lane2_xe14=0x1
+serdes_driver_current_lane3_xe14=0x1
+serdes_pre_driver_current_lane0_xe14=0x1
+serdes_pre_driver_current_lane1_xe14=0x1
+serdes_pre_driver_current_lane2_xe14=0x1
+serdes_pre_driver_current_lane3_xe14=0x1
+serdes_preemphasis_lane0_xe14=0xa760
+serdes_preemphasis_lane1_xe14=0xa760
+serdes_preemphasis_lane2_xe14=0xa760
+serdes_preemphasis_lane3_xe14=0xa760
+
+# xe15 (40G)
+portmap_16=61:40
+xgxs_rx_lane_map_16=0x132
+xgxs_tx_lane_map_16=0x213
+phy_xaui_rx_polarity_flip_16=0x0
+phy_xaui_tx_polarity_flip_16=0x0
+serdes_driver_current_lane0_xe15=0x2
+serdes_driver_current_lane1_xe15=0x2
+serdes_driver_current_lane2_xe15=0x2
+serdes_driver_current_lane3_xe15=0x2
+serdes_pre_driver_current_lane0_xe15=0x2
+serdes_pre_driver_current_lane1_xe15=0x2
+serdes_pre_driver_current_lane2_xe15=0x2
+serdes_pre_driver_current_lane3_xe15=0x2
+serdes_preemphasis_lane0_xe15=0xa760
+serdes_preemphasis_lane1_xe15=0xa760
+serdes_preemphasis_lane2_xe15=0xa760
+serdes_preemphasis_lane3_xe15=0xa760
+
+# xe16 (40G)
+portmap_17=69:40
+xgxs_rx_lane_map_17=0x213
+xgxs_tx_lane_map_17=0x2130
+phy_xaui_rx_polarity_flip_17=0x1
+phy_xaui_tx_polarity_flip_17=0xf
+serdes_driver_current_lane0_xe16=0x1
+serdes_driver_current_lane1_xe16=0x1
+serdes_driver_current_lane2_xe16=0x1
+serdes_driver_current_lane3_xe16=0x1
+serdes_pre_driver_current_lane0_xe16=0x1
+serdes_pre_driver_current_lane1_xe16=0x1
+serdes_pre_driver_current_lane2_xe16=0x1
+serdes_pre_driver_current_lane3_xe16=0x1
+serdes_preemphasis_lane0_xe16=0xa760
+serdes_preemphasis_lane1_xe16=0xa760
+serdes_preemphasis_lane2_xe16=0xa760
+serdes_preemphasis_lane3_xe16=0xa760
+
+# xe17 (40G)
+portmap_18=65:40
+xgxs_rx_lane_map_18=0x132
+xgxs_tx_lane_map_18=0x2031
+phy_xaui_rx_polarity_flip_18=0x3
+phy_xaui_tx_polarity_flip_18=0x9
+serdes_driver_current_lane0_xe17=0x1
+serdes_driver_current_lane1_xe17=0x1
+serdes_driver_current_lane2_xe17=0x1
+serdes_driver_current_lane3_xe17=0x1
+serdes_pre_driver_current_lane0_xe17=0x1
+serdes_pre_driver_current_lane1_xe17=0x1
+serdes_pre_driver_current_lane2_xe17=0x1
+serdes_pre_driver_current_lane3_xe17=0x1
+serdes_preemphasis_lane0_xe17=0xa370
+serdes_preemphasis_lane1_xe17=0xa370
+serdes_preemphasis_lane2_xe17=0xa370
+serdes_preemphasis_lane3_xe17=0xa370
+
+# xe18 (40G)
+portmap_19=73:40
+xgxs_rx_lane_map_19=0x213
+xgxs_tx_lane_map_19=0x2031
+phy_xaui_rx_polarity_flip_19=0x1
+phy_xaui_tx_polarity_flip_19=0x0
+serdes_driver_current_lane0_xe18=0x2
+serdes_driver_current_lane1_xe18=0x2
+serdes_driver_current_lane2_xe18=0x2
+serdes_driver_current_lane3_xe18=0x2
+serdes_pre_driver_current_lane0_xe18=0x2
+serdes_pre_driver_current_lane1_xe18=0x2
+serdes_pre_driver_current_lane2_xe18=0x2
+serdes_pre_driver_current_lane3_xe18=0x2
+serdes_preemphasis_lane0_xe18=0xa760
+serdes_preemphasis_lane1_xe18=0xa760
+serdes_preemphasis_lane2_xe18=0xa760
+serdes_preemphasis_lane3_xe18=0xa760
+
+# xe19 (40G)
+portmap_20=77:40
+xgxs_rx_lane_map_20=0x123
+xgxs_tx_lane_map_20=0x1203
+phy_xaui_rx_polarity_flip_20=0x3
+phy_xaui_tx_polarity_flip_20=0xe
+serdes_driver_current_lane0_xe19=0x2
+serdes_driver_current_lane1_xe19=0x2
+serdes_driver_current_lane2_xe19=0x2
+serdes_driver_current_lane3_xe19=0x2
+serdes_pre_driver_current_lane0_xe19=0x2
+serdes_pre_driver_current_lane1_xe19=0x2
+serdes_pre_driver_current_lane2_xe19=0x2
+serdes_pre_driver_current_lane3_xe19=0x2
+serdes_preemphasis_lane0_xe19=0xaf40
+serdes_preemphasis_lane1_xe19=0xaf40
+serdes_preemphasis_lane2_xe19=0xaf40
+serdes_preemphasis_lane3_xe19=0xaf40
+
+# xe20 (40G)
+portmap_21=109:40
+xgxs_rx_lane_map_21=0x132
+xgxs_tx_lane_map_21=0x132
+phy_xaui_rx_polarity_flip_21=0x8
+phy_xaui_tx_polarity_flip_21=0x0
+serdes_driver_current_lane0_xe20=0x1
+serdes_driver_current_lane1_xe20=0x1
+serdes_driver_current_lane2_xe20=0x1
+serdes_driver_current_lane3_xe20=0x2
+serdes_pre_driver_current_lane0_xe20=0x1
+serdes_pre_driver_current_lane1_xe20=0x1
+serdes_pre_driver_current_lane2_xe20=0x1
+serdes_pre_driver_current_lane3_xe20=0x2
+serdes_preemphasis_lane0_xe20=0xb330
+serdes_preemphasis_lane1_xe20=0xb330
+serdes_preemphasis_lane2_xe20=0xb330
+serdes_preemphasis_lane3_xe20=0xbff0
+
+# xe21 (40G)
+portmap_22=105:40
+xgxs_rx_lane_map_22=0x1320
+xgxs_tx_lane_map_22=0x3021
+phy_xaui_rx_polarity_flip_22=0xd
+phy_xaui_tx_polarity_flip_22=0xb
+serdes_driver_current_lane0_xe21=0x1
+serdes_driver_current_lane1_xe21=0x1
+serdes_driver_current_lane2_xe21=0x1
+serdes_driver_current_lane3_xe21=0x1
+serdes_pre_driver_current_lane0_xe21=0x1
+serdes_pre_driver_current_lane1_xe21=0x1
+serdes_pre_driver_current_lane2_xe21=0x1
+serdes_pre_driver_current_lane3_xe21=0x1
+serdes_preemphasis_lane0_xe21=0xb330
+serdes_preemphasis_lane1_xe21=0xb330
+serdes_preemphasis_lane2_xe21=0xb330
+serdes_preemphasis_lane3_xe21=0xb330
+
+# xe22 (40G)
+portmap_23=113:40
+xgxs_rx_lane_map_23=0x132
+xgxs_tx_lane_map_23=0x132
+phy_xaui_rx_polarity_flip_23=0x8
+phy_xaui_tx_polarity_flip_23=0x0
+serdes_driver_current_lane0_xe22=0x1
+serdes_driver_current_lane1_xe22=0x1
+serdes_driver_current_lane2_xe22=0x1
+serdes_driver_current_lane3_xe22=0x1
+serdes_pre_driver_current_lane0_xe22=0x1
+serdes_pre_driver_current_lane1_xe22=0x1
+serdes_pre_driver_current_lane2_xe22=0x1
+serdes_pre_driver_current_lane3_xe22=0x1
+serdes_preemphasis_lane0_xe22=0xbb10
+serdes_preemphasis_lane1_xe22=0xbb10
+serdes_preemphasis_lane2_xe22=0xbb10
+serdes_preemphasis_lane3_xe22=0xc2f0
+
+# xe23 (40G)
+portmap_24=117:40
+xgxs_rx_lane_map_24=0x231
+xgxs_tx_lane_map_24=0x1203
+phy_xaui_rx_polarity_flip_24=0x3
+phy_xaui_tx_polarity_flip_24=0xe
+serdes_driver_current_lane0_xe23=0x3
+serdes_driver_current_lane1_xe23=0x5
+serdes_driver_current_lane2_xe23=0x3
+serdes_driver_current_lane3_xe23=0x3
+serdes_pre_driver_current_lane0_xe23=0x3
+serdes_pre_driver_current_lane1_xe23=0x5
+serdes_pre_driver_current_lane2_xe23=0x3
+serdes_pre_driver_current_lane3_xe23=0x3
+serdes_preemphasis_lane0_xe23=0xc6e0
+serdes_preemphasis_lane1_xe23=0xc6e0
+serdes_preemphasis_lane2_xe23=0xc6e0
+serdes_preemphasis_lane3_xe23=0xc6e0
+
+# xe24 (40G)
+portmap_25=125:40
+xgxs_rx_lane_map_25=0x132
+xgxs_tx_lane_map_25=0x132
+phy_xaui_rx_polarity_flip_25=0x8
+phy_xaui_tx_polarity_flip_25=0x0
+serdes_driver_current_lane0_xe24=0x4
+serdes_driver_current_lane1_xe24=0x4
+serdes_driver_current_lane2_xe24=0x4
+serdes_driver_current_lane3_xe24=0x4
+serdes_pre_driver_current_lane0_xe24=0x4
+serdes_pre_driver_current_lane1_xe24=0x4
+serdes_pre_driver_current_lane2_xe24=0x4
+serdes_pre_driver_current_lane3_xe24=0x4
+serdes_preemphasis_lane0_xe24=0xc6e0
+serdes_preemphasis_lane1_xe24=0xc6e0
+serdes_preemphasis_lane2_xe24=0xc6e0
+serdes_preemphasis_lane3_xe24=0xcec0
+
+# xe25 (40G)
+portmap_26=121:40
+xgxs_rx_lane_map_26=0x1320
+xgxs_tx_lane_map_26=0x3021
+phy_xaui_rx_polarity_flip_26=0xd
+phy_xaui_tx_polarity_flip_26=0xb
+serdes_driver_current_lane0_xe25=0x4
+serdes_driver_current_lane1_xe25=0x4
+serdes_driver_current_lane2_xe25=0x4
+serdes_driver_current_lane3_xe25=0x4
+serdes_pre_driver_current_lane0_xe25=0x4
+serdes_pre_driver_current_lane1_xe25=0x4
+serdes_pre_driver_current_lane2_xe25=0x4
+serdes_pre_driver_current_lane3_xe25=0x4
+serdes_preemphasis_lane0_xe25=0xc6e0
+serdes_preemphasis_lane1_xe25=0xc6e0
+serdes_preemphasis_lane2_xe25=0xc6e0
+serdes_preemphasis_lane3_xe25=0xc6e0
+
+# xe26 (40G)
+portmap_27=81:40
+xgxs_rx_lane_map_27=0x1320
+xgxs_tx_lane_map_27=0x2031
+phy_xaui_rx_polarity_flip_27=0x1
+phy_xaui_tx_polarity_flip_27=0x2
+serdes_driver_current_lane0_xe26=0x2
+serdes_driver_current_lane1_xe26=0x2
+serdes_driver_current_lane2_xe26=0x2
+serdes_driver_current_lane3_xe26=0x2
+serdes_pre_driver_current_lane0_xe26=0x2
+serdes_pre_driver_current_lane1_xe26=0x2
+serdes_pre_driver_current_lane2_xe26=0x2
+serdes_pre_driver_current_lane3_xe26=0x2
+serdes_preemphasis_lane0_xe26=0xbb10
+serdes_preemphasis_lane1_xe26=0xbb10
+serdes_preemphasis_lane2_xe26=0xbf00
+serdes_preemphasis_lane3_xe26=0xbb10
+
+# xe27 (40G)
+portmap_28=85:40
+xgxs_rx_lane_map_28=0x213
+xgxs_tx_lane_map_28=0x1203
+phy_xaui_rx_polarity_flip_28=0xc
+phy_xaui_tx_polarity_flip_28=0xe
+serdes_driver_current_lane0_xe27=0x4
+serdes_driver_current_lane1_xe27=0x5
+serdes_driver_current_lane2_xe27=0x4
+serdes_driver_current_lane3_xe27=0x5
+serdes_pre_driver_current_lane0_xe27=0x4
+serdes_pre_driver_current_lane1_xe27=0x5
+serdes_pre_driver_current_lane2_xe27=0x4
+serdes_pre_driver_current_lane3_xe27=0x5
+serdes_preemphasis_lane0_xe27=0xc2f0
+serdes_preemphasis_lane1_xe27=0xc6e0
+serdes_preemphasis_lane2_xe27=0xc6e0
+serdes_preemphasis_lane3_xe27=0xc6e0
+
+# xe28 (40G)
+portmap_29=93:40
+xgxs_rx_lane_map_29=0x1320
+xgxs_tx_lane_map_29=0x2031
+phy_xaui_rx_polarity_flip_29=0x1
+phy_xaui_tx_polarity_flip_29=0x2
+serdes_driver_current_lane0_xe28=0x4
+serdes_driver_current_lane1_xe28=0x4
+serdes_driver_current_lane2_xe28=0x4
+serdes_driver_current_lane3_xe28=0x4
+serdes_pre_driver_current_lane0_xe28=0x4
+serdes_pre_driver_current_lane1_xe28=0x4
+serdes_pre_driver_current_lane2_xe28=0x4
+serdes_pre_driver_current_lane3_xe28=0x4
+serdes_preemphasis_lane0_xe28=0xc2f0
+serdes_preemphasis_lane1_xe28=0xc2f0
+serdes_preemphasis_lane2_xe28=0xc2f0
+serdes_preemphasis_lane3_xe28=0xc2f0
+
+# xe29 (40G)
+portmap_30=89:40
+xgxs_rx_lane_map_30=0x1320
+xgxs_tx_lane_map_30=0x3021
+phy_xaui_rx_polarity_flip_30=0x2
+phy_xaui_tx_polarity_flip_30=0xb
+serdes_driver_current_lane0_xe29=0x4
+serdes_driver_current_lane1_xe29=0x4
+serdes_driver_current_lane2_xe29=0x4
+serdes_driver_current_lane3_xe29=0x4
+serdes_pre_driver_current_lane0_xe29=0x4
+serdes_pre_driver_current_lane1_xe29=0x4
+serdes_pre_driver_current_lane2_xe29=0x4
+serdes_pre_driver_current_lane3_xe29=0x4
+serdes_preemphasis_lane0_xe29=0xcad0
+serdes_preemphasis_lane1_xe29=0xc6e0
+serdes_preemphasis_lane2_xe29=0xc6e0
+serdes_preemphasis_lane3_xe29=0xc6e0
+
+# xe30 (40G)
+portmap_31=101:40
+xgxs_rx_lane_map_31=0x1320
+xgxs_tx_lane_map_31=0x1203
+phy_xaui_rx_polarity_flip_31=0x1
+phy_xaui_tx_polarity_flip_31=0x6
+serdes_driver_current_lane0_xe30=0x6
+serdes_driver_current_lane1_xe30=0x6
+serdes_driver_current_lane2_xe30=0x6
+serdes_driver_current_lane3_xe30=0x7
+serdes_pre_driver_current_lane0_xe30=0x6
+serdes_pre_driver_current_lane1_xe30=0x6
+serdes_pre_driver_current_lane2_xe30=0x6
+serdes_pre_driver_current_lane3_xe30=0x7
+serdes_preemphasis_lane0_xe30=0xcec0
+serdes_preemphasis_lane1_xe30=0xcec0
+serdes_preemphasis_lane2_xe30=0xcad0
+serdes_preemphasis_lane3_xe30=0xc6e0
+
+# xe31 (40G)
+portmap_32=97:40
+xgxs_rx_lane_map_32=0x213
+xgxs_tx_lane_map_32=0x2031
+phy_xaui_rx_polarity_flip_32=0xc
+phy_xaui_tx_polarity_flip_32=0x3
+serdes_driver_current_lane0_xe31=0x5
+serdes_driver_current_lane1_xe31=0x5
+serdes_driver_current_lane2_xe31=0x5
+serdes_driver_current_lane3_xe31=0x5
+serdes_pre_driver_current_lane0_xe31=0x5
+serdes_pre_driver_current_lane1_xe31=0x5
+serdes_pre_driver_current_lane2_xe31=0x5
+serdes_pre_driver_current_lane3_xe31=0x5
+serdes_preemphasis_lane0_xe31=0xcad0
+serdes_preemphasis_lane1_xe31=0xcad0
+serdes_preemphasis_lane2_xe31=0xcad0
+serdes_preemphasis_lane3_xe31=0xcad0
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/buffers.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/buffers.json.j2
new file mode 100644
index 000000000000..b67cf577ab75
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/buffers.json.j2
@@ -0,0 +1,3 @@
+{%- set default_topo = 't1' %}
+{%- include 'buffers_config.j2' %}
+
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/buffers_defaults_def.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/buffers_defaults_def.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/buffers_defaults_def.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/buffers_defaults_t0.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/buffers_defaults_t0.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/buffers_defaults_t0.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/buffers_defaults_t1.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/buffers_defaults_t1.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/buffers_defaults_t1.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/lanemap.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/lanemap.ini
new file mode 100644
index 000000000000..36278a01778c
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/lanemap.ini
@@ -0,0 +1,32 @@
+eth1:25,26,27,28
+eth2:29,30,31,32
+eth3:33,34,35,36
+eth4:37,38,39,40
+eth5:45,46,47,48
+eth6:41,42,43,44
+eth7:1,2,3,4
+eth8:5,6,7,8
+eth9:13,14,15,16
+eth10:9,10,11,12
+eth11:17,18,19,20
+eth12:21,22,23,24
+eth13:53,54,55,56
+eth14:49,50,51,52
+eth15:57,58,59,60
+eth16:61,62,63,64
+eth17:69,70,71,72
+eth18:65,66,67,68
+eth19:73,74,75,76
+eth20:77,78,79,80
+eth21:109,110,111,112
+eth22:105,106,107,108
+eth23:113,114,115,116
+eth24:117,118,119,120
+eth25:125,126,127,128
+eth26:121,122,123,124
+eth27:81,82,83,84
+eth28:85,86,87,88
+eth29:93,94,95,96
+eth30:89,90,91,92
+eth31:101,102,103,104
+eth32:97,98,99,100
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/pg_profile_lookup.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/pg_profile_lookup.ini
new file mode 100644
index 000000000000..9f2eacb6fc42
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/pg_profile_lookup.ini
@@ -0,0 +1,17 @@
+# PG lossless profiles.
+# speed cable size xon xoff threshold xon_offset
+ 10000 5m 56368 18432 55120 -3 2496
+ 25000 5m 56368 18432 55120 -3 2496
+ 40000 5m 56368 18432 55120 -3 2496
+ 50000 5m 56368 18432 55120 -3 2496
+ 100000 5m 56368 18432 55120 -3 2496
+ 10000 40m 56368 18432 55120 -3 2496
+ 25000 40m 56368 18432 55120 -3 2496
+ 40000 40m 56368 18432 55120 -3 2496
+ 50000 40m 56368 18432 55120 -3 2496
+ 100000 40m 56368 18432 55120 -3 2496
+ 10000 300m 56368 18432 55120 -3 2496
+ 25000 300m 56368 18432 55120 -3 2496
+ 40000 300m 56368 18432 55120 -3 2496
+ 50000 300m 56368 18432 55120 -3 2496
+ 100000 300m 56368 18432 55120 -3 2496
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/port_config.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/port_config.ini
new file mode 100644
index 000000000000..95cf5eec9e4e
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/port_config.ini
@@ -0,0 +1,33 @@
+# name lanes alias index speed
+Ethernet0 25,26,27,28 fortyGigE0/0 0 40000
+Ethernet4 29,30,31,32 fortyGigE0/4 1 40000
+Ethernet8 33,34,35,36 fortyGigE0/8 2 40000
+Ethernet12 37,38,39,40 fortyGigE0/12 3 40000
+Ethernet16 45,46,47,48 fortyGigE0/16 4 40000
+Ethernet20 41,42,43,44 fortyGigE0/20 5 40000
+Ethernet24 1,2,3,4 fortyGigE0/24 6 40000
+Ethernet28 5,6,7,8 fortyGigE0/28 7 40000
+Ethernet32 13,14,15,16 fortyGigE0/32 8 40000
+Ethernet36 9,10,11,12 fortyGigE0/36 9 40000
+Ethernet40 17,18,19,20 fortyGigE0/40 10 40000
+Ethernet44 21,22,23,24 fortyGigE0/44 11 40000
+Ethernet48 53,54,55,56 fortyGigE0/48 12 40000
+Ethernet52 49,50,51,52 fortyGigE0/52 13 40000
+Ethernet56 57,58,59,60 fortyGigE0/56 14 40000
+Ethernet60 61,62,63,64 fortyGigE0/60 15 40000
+Ethernet64 69,70,71,72 fortyGigE0/64 16 40000
+Ethernet68 65,66,67,68 fortyGigE0/68 17 40000
+Ethernet72 73,74,75,76 fortyGigE0/72 18 40000
+Ethernet76 77,78,79,80 fortyGigE0/76 19 40000
+Ethernet80 109,110,111,112 fortyGigE0/80 20 40000
+Ethernet84 105,106,107,108 fortyGigE0/84 21 40000
+Ethernet88 113,114,115,116 fortyGigE0/88 22 40000
+Ethernet92 117,118,119,120 fortyGigE0/92 23 40000
+Ethernet96 125,126,127,128 fortyGigE0/96 24 40000
+Ethernet100 121,122,123,124 fortyGigE0/100 25 40000
+Ethernet104 81,82,83,84 fortyGigE0/104 26 40000
+Ethernet108 85,86,87,88 fortyGigE0/108 27 40000
+Ethernet112 93,94,95,96 fortyGigE0/112 28 40000
+Ethernet116 89,90,91,92 fortyGigE0/116 29 40000
+Ethernet120 101,102,103,104 fortyGigE0/120 30 40000
+Ethernet124 97,98,99,100 fortyGigE0/124 31 40000
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/qos.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/qos.json.j2
new file mode 100644
index 000000000000..3e548325ea30
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/qos.json.j2
@@ -0,0 +1 @@
+{%- include 'qos_config.j2' %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/sai.profile b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/sai.profile
new file mode 100644
index 000000000000..bfc466f27e54
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/sai.profile
@@ -0,0 +1,5 @@
+SAI_WARM_BOOT_READ_FILE=/var/cache/sai_warmboot.bin
+SAI_WARM_BOOT_WRITE_FILE=/var/cache/sai_warmboot.bin
+SAI_VS_SWITCH_TYPE=SAI_VS_SWITCH_TYPE_BCM56850
+SAI_VS_HOSTIF_USE_TAP_DEVICE=true
+SAI_VS_INTERFACE_LANE_MAP_FILE=/usr/share/sonic/hwsku/lanemap.ini
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/td2-s6000-32x40G.config.bcm b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/td2-s6000-32x40G.config.bcm
new file mode 100644
index 000000000000..4c94db7107c7
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/td2-s6000-32x40G.config.bcm
@@ -0,0 +1,646 @@
+# Old LPM only configuration
+# l2_mem_entries=163840
+# l3_mem_entries=90112
+# l3_alpm_enable=0
+# ipv6_lpm_128b_enable=0
+#
+# ALPM enable
+l3_alpm_enable=2
+ipv6_lpm_128b_enable=1
+l2_mem_entries=32768
+l3_mem_entries=16384
+
+# From old config file
+os=unix
+higig2_hdr_mode=1
+
+# Parity
+parity_correction=1
+parity_enable=1
+stat_if_parity_enable=0
+
+#
+bcm_num_cos=8
+bcm_stat_interval=2000000
+l2xmsg_hostbuf_size=8192
+l2xmsg_mode=1
+lls_num_l2uc=12
+max_vp_lags=0
+miim_intr_enable=0
+mmu_lossless=0
+module_64ports=0
+schan_intr_enable=0
+stable_size=0x2000000
+tdma_timeout_usec=5000000
+
+pbmp_oversubscribe=0x000007fffffffffffffffffffffffffe
+pbmp_xport_xe=0x000007fffffffffffffffffffffffffe
+
+# Ports configuration
+# xe0 (40G)
+portmap_1=25:40
+xgxs_rx_lane_map_1=0x213
+xgxs_tx_lane_map_1=0x2031
+phy_xaui_rx_polarity_flip_1=0xe
+phy_xaui_tx_polarity_flip_1=0x2
+serdes_driver_current_lane0_xe0=0x5
+serdes_driver_current_lane1_xe0=0x5
+serdes_driver_current_lane2_xe0=0x5
+serdes_driver_current_lane3_xe0=0x5
+serdes_pre_driver_current_lane0_xe0=0x5
+serdes_pre_driver_current_lane1_xe0=0x5
+serdes_pre_driver_current_lane2_xe0=0x5
+serdes_pre_driver_current_lane3_xe0=0x5
+serdes_preemphasis_lane0_xe0=0xcad0
+serdes_preemphasis_lane1_xe0=0xc6e0
+serdes_preemphasis_lane2_xe0=0xc6e0
+serdes_preemphasis_lane3_xe0=0xd2b0
+
+# xe1 (40G)
+portmap_2=29:40
+xgxs_rx_lane_map_2=0x213
+xgxs_tx_lane_map_2=0x213
+phy_xaui_rx_polarity_flip_2=0xc
+phy_xaui_tx_polarity_flip_2=0x9
+serdes_driver_current_lane0_xe1=0x6
+serdes_driver_current_lane1_xe1=0x7
+serdes_driver_current_lane2_xe1=0x6
+serdes_driver_current_lane3_xe1=0x6
+serdes_pre_driver_current_lane0_xe1=0x6
+serdes_pre_driver_current_lane1_xe1=0x7
+serdes_pre_driver_current_lane2_xe1=0x6
+serdes_pre_driver_current_lane3_xe1=0x6
+serdes_preemphasis_lane0_xe1=0xc2f0
+serdes_preemphasis_lane1_xe1=0xd2b0
+serdes_preemphasis_lane2_xe1=0xc6e0
+serdes_preemphasis_lane3_xe1=0xc2f0
+
+# xe2 (40G)
+portmap_3=33:40
+xgxs_rx_lane_map_3=0x213
+xgxs_tx_lane_map_3=0x132
+phy_xaui_rx_polarity_flip_3=0xe
+phy_xaui_tx_polarity_flip_3=0x2
+serdes_driver_current_lane0_xe2=0x4
+serdes_driver_current_lane1_xe2=0x4
+serdes_driver_current_lane2_xe2=0x4
+serdes_driver_current_lane3_xe2=0x4
+serdes_pre_driver_current_lane0_xe2=0x4
+serdes_pre_driver_current_lane1_xe2=0x4
+serdes_pre_driver_current_lane2_xe2=0x4
+serdes_pre_driver_current_lane3_xe2=0x4
+serdes_preemphasis_lane0_xe2=0xc6e0
+serdes_preemphasis_lane1_xe2=0xc6e0
+serdes_preemphasis_lane2_xe2=0xc6e0
+serdes_preemphasis_lane3_xe2=0xc6e0
+
+# xe3 (40G)
+portmap_4=37:40
+xgxs_rx_lane_map_4=0x213
+xgxs_tx_lane_map_4=0x1203
+phy_xaui_rx_polarity_flip_4=0x3
+phy_xaui_tx_polarity_flip_4=0xe
+serdes_driver_current_lane0_xe3=0x4
+serdes_driver_current_lane1_xe3=0x4
+serdes_driver_current_lane2_xe3=0x4
+serdes_driver_current_lane3_xe3=0x4
+serdes_pre_driver_current_lane0_xe3=0x4
+serdes_pre_driver_current_lane1_xe3=0x4
+serdes_pre_driver_current_lane2_xe3=0x4
+serdes_pre_driver_current_lane3_xe3=0x4
+serdes_preemphasis_lane0_xe3=0xcad0
+serdes_preemphasis_lane1_xe3=0xcad0
+serdes_preemphasis_lane2_xe3=0xc2f0
+serdes_preemphasis_lane3_xe3=0xc2f0
+
+# xe4 (40G)
+portmap_5=45:40
+xgxs_rx_lane_map_5=0x213
+xgxs_tx_lane_map_5=0x213
+phy_xaui_rx_polarity_flip_5=0xe
+phy_xaui_tx_polarity_flip_5=0x8
+serdes_driver_current_lane0_xe4=0x4
+serdes_driver_current_lane1_xe4=0x4
+serdes_driver_current_lane2_xe4=0x4
+serdes_driver_current_lane3_xe4=0x4
+serdes_pre_driver_current_lane0_xe4=0x4
+serdes_pre_driver_current_lane1_xe4=0x4
+serdes_pre_driver_current_lane2_xe4=0x4
+serdes_pre_driver_current_lane3_xe4=0x4
+serdes_preemphasis_lane0_xe4=0xc2f0
+serdes_preemphasis_lane1_xe4=0xc2f0
+serdes_preemphasis_lane2_xe4=0xc2f0
+serdes_preemphasis_lane3_xe4=0xc2f0
+
+# xe5 (40G)
+portmap_6=41:40
+xgxs_rx_lane_map_6=0x213
+xgxs_tx_lane_map_6=0x3021
+phy_xaui_rx_polarity_flip_6=0x3
+phy_xaui_tx_polarity_flip_6=0xb
+serdes_driver_current_lane0_xe5=0x4
+serdes_driver_current_lane1_xe5=0x4
+serdes_driver_current_lane2_xe5=0x4
+serdes_driver_current_lane3_xe5=0x4
+serdes_pre_driver_current_lane0_xe5=0x4
+serdes_pre_driver_current_lane1_xe5=0x4
+serdes_pre_driver_current_lane2_xe5=0x4
+serdes_pre_driver_current_lane3_xe5=0x4
+serdes_preemphasis_lane0_xe5=0xc6e0
+serdes_preemphasis_lane1_xe5=0xc2f0
+serdes_preemphasis_lane2_xe5=0xc2f0
+serdes_preemphasis_lane3_xe5=0xcad0
+
+# xe6 (40G)
+portmap_7=1:40
+xgxs_rx_lane_map_7=0x213
+xgxs_tx_lane_map_7=0x2031
+phy_xaui_rx_polarity_flip_7=0xe
+phy_xaui_tx_polarity_flip_7=0xd
+serdes_driver_current_lane0_xe6=0x5
+serdes_driver_current_lane1_xe6=0x5
+serdes_driver_current_lane2_xe6=0x5
+serdes_driver_current_lane3_xe6=0x5
+serdes_pre_driver_current_lane0_xe6=0x5
+serdes_pre_driver_current_lane1_xe6=0x5
+serdes_pre_driver_current_lane2_xe6=0x5
+serdes_pre_driver_current_lane3_xe6=0x5
+serdes_preemphasis_lane0_xe6=0xc6e0
+serdes_preemphasis_lane1_xe6=0xcad0
+serdes_preemphasis_lane2_xe6=0xc6e0
+serdes_preemphasis_lane3_xe6=0xcad0
+
+# xe7 (40G)
+portmap_8=5:40
+xgxs_rx_lane_map_8=0x213
+xgxs_tx_lane_map_8=0x1203
+phy_xaui_rx_polarity_flip_8=0xc
+phy_xaui_tx_polarity_flip_8=0x1
+serdes_driver_current_lane0_xe7=0x4
+serdes_driver_current_lane1_xe7=0x4
+serdes_driver_current_lane2_xe7=0x4
+serdes_driver_current_lane3_xe7=0x4
+serdes_pre_driver_current_lane0_xe7=0x4
+serdes_pre_driver_current_lane1_xe7=0x4
+serdes_pre_driver_current_lane2_xe7=0x4
+serdes_pre_driver_current_lane3_xe7=0x4
+serdes_preemphasis_lane0_xe7=0xc6e0
+serdes_preemphasis_lane1_xe7=0xc6e0
+serdes_preemphasis_lane2_xe7=0xc6e0
+serdes_preemphasis_lane3_xe7=0xc6e0
+
+# xe8 (40G)
+portmap_9=13:40
+xgxs_rx_lane_map_9=0x213
+xgxs_tx_lane_map_9=0x132
+phy_xaui_rx_polarity_flip_9=0xe
+phy_xaui_tx_polarity_flip_9=0x0
+serdes_driver_current_lane0_xe8=0x2
+serdes_driver_current_lane1_xe8=0x3
+serdes_driver_current_lane2_xe8=0x2
+serdes_driver_current_lane3_xe8=0x2
+serdes_pre_driver_current_lane0_xe8=0x2
+serdes_pre_driver_current_lane1_xe8=0x3
+serdes_pre_driver_current_lane2_xe8=0x2
+serdes_pre_driver_current_lane3_xe8=0x2
+serdes_preemphasis_lane0_xe8=0xb270
+serdes_preemphasis_lane1_xe8=0xbb10
+serdes_preemphasis_lane2_xe8=0xb720
+serdes_preemphasis_lane3_xe8=0xb720
+
+# xe9 (40G)
+portmap_10=9:40
+xgxs_rx_lane_map_10=0x3120
+xgxs_tx_lane_map_10=0x3021
+phy_xaui_rx_polarity_flip_10=0x0
+phy_xaui_tx_polarity_flip_10=0x4
+serdes_driver_current_lane0_xe9=0x3
+serdes_driver_current_lane1_xe9=0x3
+serdes_driver_current_lane2_xe9=0x3
+serdes_driver_current_lane3_xe9=0x3
+serdes_pre_driver_current_lane0_xe9=0x3
+serdes_pre_driver_current_lane1_xe9=0x3
+serdes_pre_driver_current_lane2_xe9=0x3
+serdes_pre_driver_current_lane3_xe9=0x3
+serdes_preemphasis_lane0_xe9=0xc2f0
+serdes_preemphasis_lane1_xe9=0xc6e0
+serdes_preemphasis_lane2_xe9=0xbf00
+serdes_preemphasis_lane3_xe9=0xc2f0
+
+# xe10 (40G)
+portmap_11=17:40
+xgxs_rx_lane_map_11=0x213
+xgxs_tx_lane_map_11=0x132
+phy_xaui_rx_polarity_flip_11=0xe
+phy_xaui_tx_polarity_flip_11=0x0
+serdes_driver_current_lane0_xe10=0x2
+serdes_driver_current_lane1_xe10=0x2
+serdes_driver_current_lane2_xe10=0x2
+serdes_driver_current_lane3_xe10=0x2
+serdes_pre_driver_current_lane0_xe10=0x2
+serdes_pre_driver_current_lane1_xe10=0x2
+serdes_pre_driver_current_lane2_xe10=0x2
+serdes_pre_driver_current_lane3_xe10=0x2
+serdes_preemphasis_lane0_xe10=0xb330
+serdes_preemphasis_lane1_xe10=0xbb10
+serdes_preemphasis_lane2_xe10=0xbb10
+serdes_preemphasis_lane3_xe10=0xbb10
+
+# xe11 (40G)
+portmap_12=21:40
+xgxs_rx_lane_map_12=0x123
+xgxs_tx_lane_map_12=0x1203
+phy_xaui_rx_polarity_flip_12=0xc
+phy_xaui_tx_polarity_flip_12=0xe
+serdes_driver_current_lane0_xe11=0x2
+serdes_driver_current_lane1_xe11=0x2
+serdes_driver_current_lane2_xe11=0x2
+serdes_driver_current_lane3_xe11=0x2
+serdes_pre_driver_current_lane0_xe11=0x2
+serdes_pre_driver_current_lane1_xe11=0x2
+serdes_pre_driver_current_lane2_xe11=0x2
+serdes_pre_driver_current_lane3_xe11=0x2
+serdes_preemphasis_lane0_xe11=0xb330
+serdes_preemphasis_lane1_xe11=0xb330
+serdes_preemphasis_lane2_xe11=0xb330
+serdes_preemphasis_lane3_xe11=0xb330
+
+# xe12 (40G)
+portmap_13=53:40
+xgxs_rx_lane_map_13=0x213
+xgxs_tx_lane_map_13=0x231
+phy_xaui_rx_polarity_flip_13=0x1
+phy_xaui_tx_polarity_flip_13=0x0
+serdes_driver_current_lane0_xe12=0x2
+serdes_driver_current_lane1_xe12=0x2
+serdes_driver_current_lane2_xe12=0x2
+serdes_driver_current_lane3_xe12=0x2
+serdes_pre_driver_current_lane0_xe12=0x2
+serdes_pre_driver_current_lane1_xe12=0x2
+serdes_pre_driver_current_lane2_xe12=0x2
+serdes_pre_driver_current_lane3_xe12=0x2
+serdes_preemphasis_lane0_xe12=0xaf40
+serdes_preemphasis_lane1_xe12=0xaf40
+serdes_preemphasis_lane2_xe12=0xaf40
+serdes_preemphasis_lane3_xe12=0xaf40
+
+# xe13 (40G)
+portmap_14=49:40
+xgxs_rx_lane_map_14=0x1302
+xgxs_tx_lane_map_14=0x2031
+phy_xaui_rx_polarity_flip_14=0xb
+phy_xaui_tx_polarity_flip_14=0x3
+serdes_driver_current_lane0_xe13=0x2
+serdes_driver_current_lane1_xe13=0x2
+serdes_driver_current_lane2_xe13=0x2
+serdes_driver_current_lane3_xe13=0x2
+serdes_pre_driver_current_lane0_xe13=0x2
+serdes_pre_driver_current_lane1_xe13=0x2
+serdes_pre_driver_current_lane2_xe13=0x2
+serdes_pre_driver_current_lane3_xe13=0x2
+serdes_preemphasis_lane0_xe13=0xa760
+serdes_preemphasis_lane1_xe13=0xa760
+serdes_preemphasis_lane2_xe13=0xa760
+serdes_preemphasis_lane3_xe13=0xa760
+
+# xe14 (40G)
+portmap_15=57:40
+xgxs_rx_lane_map_15=0x213
+xgxs_tx_lane_map_15=0x2031
+phy_xaui_rx_polarity_flip_15=0x1
+phy_xaui_tx_polarity_flip_15=0x0
+serdes_driver_current_lane0_xe14=0x1
+serdes_driver_current_lane1_xe14=0x1
+serdes_driver_current_lane2_xe14=0x1
+serdes_driver_current_lane3_xe14=0x1
+serdes_pre_driver_current_lane0_xe14=0x1
+serdes_pre_driver_current_lane1_xe14=0x1
+serdes_pre_driver_current_lane2_xe14=0x1
+serdes_pre_driver_current_lane3_xe14=0x1
+serdes_preemphasis_lane0_xe14=0xa760
+serdes_preemphasis_lane1_xe14=0xa760
+serdes_preemphasis_lane2_xe14=0xa760
+serdes_preemphasis_lane3_xe14=0xa760
+
+# xe15 (40G)
+portmap_16=61:40
+xgxs_rx_lane_map_16=0x132
+xgxs_tx_lane_map_16=0x213
+phy_xaui_rx_polarity_flip_16=0x0
+phy_xaui_tx_polarity_flip_16=0x0
+serdes_driver_current_lane0_xe15=0x2
+serdes_driver_current_lane1_xe15=0x2
+serdes_driver_current_lane2_xe15=0x2
+serdes_driver_current_lane3_xe15=0x2
+serdes_pre_driver_current_lane0_xe15=0x2
+serdes_pre_driver_current_lane1_xe15=0x2
+serdes_pre_driver_current_lane2_xe15=0x2
+serdes_pre_driver_current_lane3_xe15=0x2
+serdes_preemphasis_lane0_xe15=0xa760
+serdes_preemphasis_lane1_xe15=0xa760
+serdes_preemphasis_lane2_xe15=0xa760
+serdes_preemphasis_lane3_xe15=0xa760
+
+# xe16 (40G)
+portmap_17=69:40
+xgxs_rx_lane_map_17=0x213
+xgxs_tx_lane_map_17=0x2130
+phy_xaui_rx_polarity_flip_17=0x1
+phy_xaui_tx_polarity_flip_17=0xf
+serdes_driver_current_lane0_xe16=0x1
+serdes_driver_current_lane1_xe16=0x1
+serdes_driver_current_lane2_xe16=0x1
+serdes_driver_current_lane3_xe16=0x1
+serdes_pre_driver_current_lane0_xe16=0x1
+serdes_pre_driver_current_lane1_xe16=0x1
+serdes_pre_driver_current_lane2_xe16=0x1
+serdes_pre_driver_current_lane3_xe16=0x1
+serdes_preemphasis_lane0_xe16=0xa760
+serdes_preemphasis_lane1_xe16=0xa760
+serdes_preemphasis_lane2_xe16=0xa760
+serdes_preemphasis_lane3_xe16=0xa760
+
+# xe17 (40G)
+portmap_18=65:40
+xgxs_rx_lane_map_18=0x132
+xgxs_tx_lane_map_18=0x2031
+phy_xaui_rx_polarity_flip_18=0x3
+phy_xaui_tx_polarity_flip_18=0x9
+serdes_driver_current_lane0_xe17=0x1
+serdes_driver_current_lane1_xe17=0x1
+serdes_driver_current_lane2_xe17=0x1
+serdes_driver_current_lane3_xe17=0x1
+serdes_pre_driver_current_lane0_xe17=0x1
+serdes_pre_driver_current_lane1_xe17=0x1
+serdes_pre_driver_current_lane2_xe17=0x1
+serdes_pre_driver_current_lane3_xe17=0x1
+serdes_preemphasis_lane0_xe17=0xa370
+serdes_preemphasis_lane1_xe17=0xa370
+serdes_preemphasis_lane2_xe17=0xa370
+serdes_preemphasis_lane3_xe17=0xa370
+
+# xe18 (40G)
+portmap_19=73:40
+xgxs_rx_lane_map_19=0x213
+xgxs_tx_lane_map_19=0x2031
+phy_xaui_rx_polarity_flip_19=0x1
+phy_xaui_tx_polarity_flip_19=0x0
+serdes_driver_current_lane0_xe18=0x2
+serdes_driver_current_lane1_xe18=0x2
+serdes_driver_current_lane2_xe18=0x2
+serdes_driver_current_lane3_xe18=0x2
+serdes_pre_driver_current_lane0_xe18=0x2
+serdes_pre_driver_current_lane1_xe18=0x2
+serdes_pre_driver_current_lane2_xe18=0x2
+serdes_pre_driver_current_lane3_xe18=0x2
+serdes_preemphasis_lane0_xe18=0xa760
+serdes_preemphasis_lane1_xe18=0xa760
+serdes_preemphasis_lane2_xe18=0xa760
+serdes_preemphasis_lane3_xe18=0xa760
+
+# xe19 (40G)
+portmap_20=77:40
+xgxs_rx_lane_map_20=0x123
+xgxs_tx_lane_map_20=0x1203
+phy_xaui_rx_polarity_flip_20=0x3
+phy_xaui_tx_polarity_flip_20=0xe
+serdes_driver_current_lane0_xe19=0x2
+serdes_driver_current_lane1_xe19=0x2
+serdes_driver_current_lane2_xe19=0x2
+serdes_driver_current_lane3_xe19=0x2
+serdes_pre_driver_current_lane0_xe19=0x2
+serdes_pre_driver_current_lane1_xe19=0x2
+serdes_pre_driver_current_lane2_xe19=0x2
+serdes_pre_driver_current_lane3_xe19=0x2
+serdes_preemphasis_lane0_xe19=0xaf40
+serdes_preemphasis_lane1_xe19=0xaf40
+serdes_preemphasis_lane2_xe19=0xaf40
+serdes_preemphasis_lane3_xe19=0xaf40
+
+# xe20 (40G)
+portmap_21=109:40
+xgxs_rx_lane_map_21=0x132
+xgxs_tx_lane_map_21=0x132
+phy_xaui_rx_polarity_flip_21=0x8
+phy_xaui_tx_polarity_flip_21=0x0
+serdes_driver_current_lane0_xe20=0x1
+serdes_driver_current_lane1_xe20=0x1
+serdes_driver_current_lane2_xe20=0x1
+serdes_driver_current_lane3_xe20=0x2
+serdes_pre_driver_current_lane0_xe20=0x1
+serdes_pre_driver_current_lane1_xe20=0x1
+serdes_pre_driver_current_lane2_xe20=0x1
+serdes_pre_driver_current_lane3_xe20=0x2
+serdes_preemphasis_lane0_xe20=0xb330
+serdes_preemphasis_lane1_xe20=0xb330
+serdes_preemphasis_lane2_xe20=0xb330
+serdes_preemphasis_lane3_xe20=0xbff0
+
+# xe21 (40G)
+portmap_22=105:40
+xgxs_rx_lane_map_22=0x1320
+xgxs_tx_lane_map_22=0x3021
+phy_xaui_rx_polarity_flip_22=0xd
+phy_xaui_tx_polarity_flip_22=0xb
+serdes_driver_current_lane0_xe21=0x1
+serdes_driver_current_lane1_xe21=0x1
+serdes_driver_current_lane2_xe21=0x1
+serdes_driver_current_lane3_xe21=0x1
+serdes_pre_driver_current_lane0_xe21=0x1
+serdes_pre_driver_current_lane1_xe21=0x1
+serdes_pre_driver_current_lane2_xe21=0x1
+serdes_pre_driver_current_lane3_xe21=0x1
+serdes_preemphasis_lane0_xe21=0xb330
+serdes_preemphasis_lane1_xe21=0xb330
+serdes_preemphasis_lane2_xe21=0xb330
+serdes_preemphasis_lane3_xe21=0xb330
+
+# xe22 (40G)
+portmap_23=113:40
+xgxs_rx_lane_map_23=0x132
+xgxs_tx_lane_map_23=0x132
+phy_xaui_rx_polarity_flip_23=0x8
+phy_xaui_tx_polarity_flip_23=0x0
+serdes_driver_current_lane0_xe22=0x1
+serdes_driver_current_lane1_xe22=0x1
+serdes_driver_current_lane2_xe22=0x1
+serdes_driver_current_lane3_xe22=0x1
+serdes_pre_driver_current_lane0_xe22=0x1
+serdes_pre_driver_current_lane1_xe22=0x1
+serdes_pre_driver_current_lane2_xe22=0x1
+serdes_pre_driver_current_lane3_xe22=0x1
+serdes_preemphasis_lane0_xe22=0xbb10
+serdes_preemphasis_lane1_xe22=0xbb10
+serdes_preemphasis_lane2_xe22=0xbb10
+serdes_preemphasis_lane3_xe22=0xc2f0
+
+# xe23 (40G)
+portmap_24=117:40
+xgxs_rx_lane_map_24=0x231
+xgxs_tx_lane_map_24=0x1203
+phy_xaui_rx_polarity_flip_24=0x3
+phy_xaui_tx_polarity_flip_24=0xe
+serdes_driver_current_lane0_xe23=0x3
+serdes_driver_current_lane1_xe23=0x5
+serdes_driver_current_lane2_xe23=0x3
+serdes_driver_current_lane3_xe23=0x3
+serdes_pre_driver_current_lane0_xe23=0x3
+serdes_pre_driver_current_lane1_xe23=0x5
+serdes_pre_driver_current_lane2_xe23=0x3
+serdes_pre_driver_current_lane3_xe23=0x3
+serdes_preemphasis_lane0_xe23=0xc6e0
+serdes_preemphasis_lane1_xe23=0xc6e0
+serdes_preemphasis_lane2_xe23=0xc6e0
+serdes_preemphasis_lane3_xe23=0xc6e0
+
+# xe24 (40G)
+portmap_25=125:40
+xgxs_rx_lane_map_25=0x132
+xgxs_tx_lane_map_25=0x132
+phy_xaui_rx_polarity_flip_25=0x8
+phy_xaui_tx_polarity_flip_25=0x0
+serdes_driver_current_lane0_xe24=0x4
+serdes_driver_current_lane1_xe24=0x4
+serdes_driver_current_lane2_xe24=0x4
+serdes_driver_current_lane3_xe24=0x4
+serdes_pre_driver_current_lane0_xe24=0x4
+serdes_pre_driver_current_lane1_xe24=0x4
+serdes_pre_driver_current_lane2_xe24=0x4
+serdes_pre_driver_current_lane3_xe24=0x4
+serdes_preemphasis_lane0_xe24=0xc6e0
+serdes_preemphasis_lane1_xe24=0xc6e0
+serdes_preemphasis_lane2_xe24=0xc6e0
+serdes_preemphasis_lane3_xe24=0xcec0
+
+# xe25 (40G)
+portmap_26=121:40
+xgxs_rx_lane_map_26=0x1320
+xgxs_tx_lane_map_26=0x3021
+phy_xaui_rx_polarity_flip_26=0xd
+phy_xaui_tx_polarity_flip_26=0xb
+serdes_driver_current_lane0_xe25=0x4
+serdes_driver_current_lane1_xe25=0x4
+serdes_driver_current_lane2_xe25=0x4
+serdes_driver_current_lane3_xe25=0x4
+serdes_pre_driver_current_lane0_xe25=0x4
+serdes_pre_driver_current_lane1_xe25=0x4
+serdes_pre_driver_current_lane2_xe25=0x4
+serdes_pre_driver_current_lane3_xe25=0x4
+serdes_preemphasis_lane0_xe25=0xc6e0
+serdes_preemphasis_lane1_xe25=0xc6e0
+serdes_preemphasis_lane2_xe25=0xc6e0
+serdes_preemphasis_lane3_xe25=0xc6e0
+
+# xe26 (40G)
+portmap_27=81:40
+xgxs_rx_lane_map_27=0x1320
+xgxs_tx_lane_map_27=0x2031
+phy_xaui_rx_polarity_flip_27=0x1
+phy_xaui_tx_polarity_flip_27=0x2
+serdes_driver_current_lane0_xe26=0x2
+serdes_driver_current_lane1_xe26=0x2
+serdes_driver_current_lane2_xe26=0x2
+serdes_driver_current_lane3_xe26=0x2
+serdes_pre_driver_current_lane0_xe26=0x2
+serdes_pre_driver_current_lane1_xe26=0x2
+serdes_pre_driver_current_lane2_xe26=0x2
+serdes_pre_driver_current_lane3_xe26=0x2
+serdes_preemphasis_lane0_xe26=0xbb10
+serdes_preemphasis_lane1_xe26=0xbb10
+serdes_preemphasis_lane2_xe26=0xbf00
+serdes_preemphasis_lane3_xe26=0xbb10
+
+# xe27 (40G)
+portmap_28=85:40
+xgxs_rx_lane_map_28=0x213
+xgxs_tx_lane_map_28=0x1203
+phy_xaui_rx_polarity_flip_28=0xc
+phy_xaui_tx_polarity_flip_28=0xe
+serdes_driver_current_lane0_xe27=0x4
+serdes_driver_current_lane1_xe27=0x5
+serdes_driver_current_lane2_xe27=0x4
+serdes_driver_current_lane3_xe27=0x5
+serdes_pre_driver_current_lane0_xe27=0x4
+serdes_pre_driver_current_lane1_xe27=0x5
+serdes_pre_driver_current_lane2_xe27=0x4
+serdes_pre_driver_current_lane3_xe27=0x5
+serdes_preemphasis_lane0_xe27=0xc2f0
+serdes_preemphasis_lane1_xe27=0xc6e0
+serdes_preemphasis_lane2_xe27=0xc6e0
+serdes_preemphasis_lane3_xe27=0xc6e0
+
+# xe28 (40G)
+portmap_29=93:40
+xgxs_rx_lane_map_29=0x1320
+xgxs_tx_lane_map_29=0x2031
+phy_xaui_rx_polarity_flip_29=0x1
+phy_xaui_tx_polarity_flip_29=0x2
+serdes_driver_current_lane0_xe28=0x4
+serdes_driver_current_lane1_xe28=0x4
+serdes_driver_current_lane2_xe28=0x4
+serdes_driver_current_lane3_xe28=0x4
+serdes_pre_driver_current_lane0_xe28=0x4
+serdes_pre_driver_current_lane1_xe28=0x4
+serdes_pre_driver_current_lane2_xe28=0x4
+serdes_pre_driver_current_lane3_xe28=0x4
+serdes_preemphasis_lane0_xe28=0xc2f0
+serdes_preemphasis_lane1_xe28=0xc2f0
+serdes_preemphasis_lane2_xe28=0xc2f0
+serdes_preemphasis_lane3_xe28=0xc2f0
+
+# xe29 (40G)
+portmap_30=89:40
+xgxs_rx_lane_map_30=0x1320
+xgxs_tx_lane_map_30=0x3021
+phy_xaui_rx_polarity_flip_30=0x2
+phy_xaui_tx_polarity_flip_30=0xb
+serdes_driver_current_lane0_xe29=0x4
+serdes_driver_current_lane1_xe29=0x4
+serdes_driver_current_lane2_xe29=0x4
+serdes_driver_current_lane3_xe29=0x4
+serdes_pre_driver_current_lane0_xe29=0x4
+serdes_pre_driver_current_lane1_xe29=0x4
+serdes_pre_driver_current_lane2_xe29=0x4
+serdes_pre_driver_current_lane3_xe29=0x4
+serdes_preemphasis_lane0_xe29=0xcad0
+serdes_preemphasis_lane1_xe29=0xc6e0
+serdes_preemphasis_lane2_xe29=0xc6e0
+serdes_preemphasis_lane3_xe29=0xc6e0
+
+# xe30 (40G)
+portmap_31=101:40
+xgxs_rx_lane_map_31=0x1320
+xgxs_tx_lane_map_31=0x1203
+phy_xaui_rx_polarity_flip_31=0x1
+phy_xaui_tx_polarity_flip_31=0x6
+serdes_driver_current_lane0_xe30=0x6
+serdes_driver_current_lane1_xe30=0x6
+serdes_driver_current_lane2_xe30=0x6
+serdes_driver_current_lane3_xe30=0x7
+serdes_pre_driver_current_lane0_xe30=0x6
+serdes_pre_driver_current_lane1_xe30=0x6
+serdes_pre_driver_current_lane2_xe30=0x6
+serdes_pre_driver_current_lane3_xe30=0x7
+serdes_preemphasis_lane0_xe30=0xcec0
+serdes_preemphasis_lane1_xe30=0xcec0
+serdes_preemphasis_lane2_xe30=0xcad0
+serdes_preemphasis_lane3_xe30=0xc6e0
+
+# xe31 (40G)
+portmap_32=97:40
+xgxs_rx_lane_map_32=0x213
+xgxs_tx_lane_map_32=0x2031
+phy_xaui_rx_polarity_flip_32=0xc
+phy_xaui_tx_polarity_flip_32=0x3
+serdes_driver_current_lane0_xe31=0x5
+serdes_driver_current_lane1_xe31=0x5
+serdes_driver_current_lane2_xe31=0x5
+serdes_driver_current_lane3_xe31=0x5
+serdes_pre_driver_current_lane0_xe31=0x5
+serdes_pre_driver_current_lane1_xe31=0x5
+serdes_pre_driver_current_lane2_xe31=0x5
+serdes_pre_driver_current_lane3_xe31=0x5
+serdes_preemphasis_lane0_xe31=0xcad0
+serdes_preemphasis_lane1_xe31=0xcad0
+serdes_preemphasis_lane2_xe31=0xcad0
+serdes_preemphasis_lane3_xe31=0xcad0
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/buffers.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/buffers.json.j2
new file mode 100644
index 000000000000..b67cf577ab75
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/buffers.json.j2
@@ -0,0 +1,3 @@
+{%- set default_topo = 't1' %}
+{%- include 'buffers_config.j2' %}
+
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/buffers_defaults_def.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/buffers_defaults_def.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/buffers_defaults_def.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/buffers_defaults_t0.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/buffers_defaults_t0.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/buffers_defaults_t0.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/buffers_defaults_t1.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/buffers_defaults_t1.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/buffers_defaults_t1.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/lanemap.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/lanemap.ini
new file mode 100644
index 000000000000..36278a01778c
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/lanemap.ini
@@ -0,0 +1,32 @@
+eth1:25,26,27,28
+eth2:29,30,31,32
+eth3:33,34,35,36
+eth4:37,38,39,40
+eth5:45,46,47,48
+eth6:41,42,43,44
+eth7:1,2,3,4
+eth8:5,6,7,8
+eth9:13,14,15,16
+eth10:9,10,11,12
+eth11:17,18,19,20
+eth12:21,22,23,24
+eth13:53,54,55,56
+eth14:49,50,51,52
+eth15:57,58,59,60
+eth16:61,62,63,64
+eth17:69,70,71,72
+eth18:65,66,67,68
+eth19:73,74,75,76
+eth20:77,78,79,80
+eth21:109,110,111,112
+eth22:105,106,107,108
+eth23:113,114,115,116
+eth24:117,118,119,120
+eth25:125,126,127,128
+eth26:121,122,123,124
+eth27:81,82,83,84
+eth28:85,86,87,88
+eth29:93,94,95,96
+eth30:89,90,91,92
+eth31:101,102,103,104
+eth32:97,98,99,100
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/pg_profile_lookup.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/pg_profile_lookup.ini
new file mode 100644
index 000000000000..9f2eacb6fc42
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/pg_profile_lookup.ini
@@ -0,0 +1,17 @@
+# PG lossless profiles.
+# speed cable size xon xoff threshold xon_offset
+ 10000 5m 56368 18432 55120 -3 2496
+ 25000 5m 56368 18432 55120 -3 2496
+ 40000 5m 56368 18432 55120 -3 2496
+ 50000 5m 56368 18432 55120 -3 2496
+ 100000 5m 56368 18432 55120 -3 2496
+ 10000 40m 56368 18432 55120 -3 2496
+ 25000 40m 56368 18432 55120 -3 2496
+ 40000 40m 56368 18432 55120 -3 2496
+ 50000 40m 56368 18432 55120 -3 2496
+ 100000 40m 56368 18432 55120 -3 2496
+ 10000 300m 56368 18432 55120 -3 2496
+ 25000 300m 56368 18432 55120 -3 2496
+ 40000 300m 56368 18432 55120 -3 2496
+ 50000 300m 56368 18432 55120 -3 2496
+ 100000 300m 56368 18432 55120 -3 2496
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/port_config.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/port_config.ini
new file mode 100644
index 000000000000..95cf5eec9e4e
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/port_config.ini
@@ -0,0 +1,33 @@
+# name lanes alias index speed
+Ethernet0 25,26,27,28 fortyGigE0/0 0 40000
+Ethernet4 29,30,31,32 fortyGigE0/4 1 40000
+Ethernet8 33,34,35,36 fortyGigE0/8 2 40000
+Ethernet12 37,38,39,40 fortyGigE0/12 3 40000
+Ethernet16 45,46,47,48 fortyGigE0/16 4 40000
+Ethernet20 41,42,43,44 fortyGigE0/20 5 40000
+Ethernet24 1,2,3,4 fortyGigE0/24 6 40000
+Ethernet28 5,6,7,8 fortyGigE0/28 7 40000
+Ethernet32 13,14,15,16 fortyGigE0/32 8 40000
+Ethernet36 9,10,11,12 fortyGigE0/36 9 40000
+Ethernet40 17,18,19,20 fortyGigE0/40 10 40000
+Ethernet44 21,22,23,24 fortyGigE0/44 11 40000
+Ethernet48 53,54,55,56 fortyGigE0/48 12 40000
+Ethernet52 49,50,51,52 fortyGigE0/52 13 40000
+Ethernet56 57,58,59,60 fortyGigE0/56 14 40000
+Ethernet60 61,62,63,64 fortyGigE0/60 15 40000
+Ethernet64 69,70,71,72 fortyGigE0/64 16 40000
+Ethernet68 65,66,67,68 fortyGigE0/68 17 40000
+Ethernet72 73,74,75,76 fortyGigE0/72 18 40000
+Ethernet76 77,78,79,80 fortyGigE0/76 19 40000
+Ethernet80 109,110,111,112 fortyGigE0/80 20 40000
+Ethernet84 105,106,107,108 fortyGigE0/84 21 40000
+Ethernet88 113,114,115,116 fortyGigE0/88 22 40000
+Ethernet92 117,118,119,120 fortyGigE0/92 23 40000
+Ethernet96 125,126,127,128 fortyGigE0/96 24 40000
+Ethernet100 121,122,123,124 fortyGigE0/100 25 40000
+Ethernet104 81,82,83,84 fortyGigE0/104 26 40000
+Ethernet108 85,86,87,88 fortyGigE0/108 27 40000
+Ethernet112 93,94,95,96 fortyGigE0/112 28 40000
+Ethernet116 89,90,91,92 fortyGigE0/116 29 40000
+Ethernet120 101,102,103,104 fortyGigE0/120 30 40000
+Ethernet124 97,98,99,100 fortyGigE0/124 31 40000
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/qos.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/qos.json.j2
new file mode 100644
index 000000000000..3e548325ea30
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/qos.json.j2
@@ -0,0 +1 @@
+{%- include 'qos_config.j2' %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/sai.profile b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/sai.profile
new file mode 100644
index 000000000000..bfc466f27e54
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/sai.profile
@@ -0,0 +1,5 @@
+SAI_WARM_BOOT_READ_FILE=/var/cache/sai_warmboot.bin
+SAI_WARM_BOOT_WRITE_FILE=/var/cache/sai_warmboot.bin
+SAI_VS_SWITCH_TYPE=SAI_VS_SWITCH_TYPE_BCM56850
+SAI_VS_HOSTIF_USE_TAP_DEVICE=true
+SAI_VS_INTERFACE_LANE_MAP_FILE=/usr/share/sonic/hwsku/lanemap.ini
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/td2-s6000-32x40G.config.bcm b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/td2-s6000-32x40G.config.bcm
new file mode 100644
index 000000000000..4c94db7107c7
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/td2-s6000-32x40G.config.bcm
@@ -0,0 +1,646 @@
+# Old LPM only configuration
+# l2_mem_entries=163840
+# l3_mem_entries=90112
+# l3_alpm_enable=0
+# ipv6_lpm_128b_enable=0
+#
+# ALPM enable
+l3_alpm_enable=2
+ipv6_lpm_128b_enable=1
+l2_mem_entries=32768
+l3_mem_entries=16384
+
+# From old config file
+os=unix
+higig2_hdr_mode=1
+
+# Parity
+parity_correction=1
+parity_enable=1
+stat_if_parity_enable=0
+
+#
+bcm_num_cos=8
+bcm_stat_interval=2000000
+l2xmsg_hostbuf_size=8192
+l2xmsg_mode=1
+lls_num_l2uc=12
+max_vp_lags=0
+miim_intr_enable=0
+mmu_lossless=0
+module_64ports=0
+schan_intr_enable=0
+stable_size=0x2000000
+tdma_timeout_usec=5000000
+
+pbmp_oversubscribe=0x000007fffffffffffffffffffffffffe
+pbmp_xport_xe=0x000007fffffffffffffffffffffffffe
+
+# Ports configuration
+# xe0 (40G)
+portmap_1=25:40
+xgxs_rx_lane_map_1=0x213
+xgxs_tx_lane_map_1=0x2031
+phy_xaui_rx_polarity_flip_1=0xe
+phy_xaui_tx_polarity_flip_1=0x2
+serdes_driver_current_lane0_xe0=0x5
+serdes_driver_current_lane1_xe0=0x5
+serdes_driver_current_lane2_xe0=0x5
+serdes_driver_current_lane3_xe0=0x5
+serdes_pre_driver_current_lane0_xe0=0x5
+serdes_pre_driver_current_lane1_xe0=0x5
+serdes_pre_driver_current_lane2_xe0=0x5
+serdes_pre_driver_current_lane3_xe0=0x5
+serdes_preemphasis_lane0_xe0=0xcad0
+serdes_preemphasis_lane1_xe0=0xc6e0
+serdes_preemphasis_lane2_xe0=0xc6e0
+serdes_preemphasis_lane3_xe0=0xd2b0
+
+# xe1 (40G)
+portmap_2=29:40
+xgxs_rx_lane_map_2=0x213
+xgxs_tx_lane_map_2=0x213
+phy_xaui_rx_polarity_flip_2=0xc
+phy_xaui_tx_polarity_flip_2=0x9
+serdes_driver_current_lane0_xe1=0x6
+serdes_driver_current_lane1_xe1=0x7
+serdes_driver_current_lane2_xe1=0x6
+serdes_driver_current_lane3_xe1=0x6
+serdes_pre_driver_current_lane0_xe1=0x6
+serdes_pre_driver_current_lane1_xe1=0x7
+serdes_pre_driver_current_lane2_xe1=0x6
+serdes_pre_driver_current_lane3_xe1=0x6
+serdes_preemphasis_lane0_xe1=0xc2f0
+serdes_preemphasis_lane1_xe1=0xd2b0
+serdes_preemphasis_lane2_xe1=0xc6e0
+serdes_preemphasis_lane3_xe1=0xc2f0
+
+# xe2 (40G)
+portmap_3=33:40
+xgxs_rx_lane_map_3=0x213
+xgxs_tx_lane_map_3=0x132
+phy_xaui_rx_polarity_flip_3=0xe
+phy_xaui_tx_polarity_flip_3=0x2
+serdes_driver_current_lane0_xe2=0x4
+serdes_driver_current_lane1_xe2=0x4
+serdes_driver_current_lane2_xe2=0x4
+serdes_driver_current_lane3_xe2=0x4
+serdes_pre_driver_current_lane0_xe2=0x4
+serdes_pre_driver_current_lane1_xe2=0x4
+serdes_pre_driver_current_lane2_xe2=0x4
+serdes_pre_driver_current_lane3_xe2=0x4
+serdes_preemphasis_lane0_xe2=0xc6e0
+serdes_preemphasis_lane1_xe2=0xc6e0
+serdes_preemphasis_lane2_xe2=0xc6e0
+serdes_preemphasis_lane3_xe2=0xc6e0
+
+# xe3 (40G)
+portmap_4=37:40
+xgxs_rx_lane_map_4=0x213
+xgxs_tx_lane_map_4=0x1203
+phy_xaui_rx_polarity_flip_4=0x3
+phy_xaui_tx_polarity_flip_4=0xe
+serdes_driver_current_lane0_xe3=0x4
+serdes_driver_current_lane1_xe3=0x4
+serdes_driver_current_lane2_xe3=0x4
+serdes_driver_current_lane3_xe3=0x4
+serdes_pre_driver_current_lane0_xe3=0x4
+serdes_pre_driver_current_lane1_xe3=0x4
+serdes_pre_driver_current_lane2_xe3=0x4
+serdes_pre_driver_current_lane3_xe3=0x4
+serdes_preemphasis_lane0_xe3=0xcad0
+serdes_preemphasis_lane1_xe3=0xcad0
+serdes_preemphasis_lane2_xe3=0xc2f0
+serdes_preemphasis_lane3_xe3=0xc2f0
+
+# xe4 (40G)
+portmap_5=45:40
+xgxs_rx_lane_map_5=0x213
+xgxs_tx_lane_map_5=0x213
+phy_xaui_rx_polarity_flip_5=0xe
+phy_xaui_tx_polarity_flip_5=0x8
+serdes_driver_current_lane0_xe4=0x4
+serdes_driver_current_lane1_xe4=0x4
+serdes_driver_current_lane2_xe4=0x4
+serdes_driver_current_lane3_xe4=0x4
+serdes_pre_driver_current_lane0_xe4=0x4
+serdes_pre_driver_current_lane1_xe4=0x4
+serdes_pre_driver_current_lane2_xe4=0x4
+serdes_pre_driver_current_lane3_xe4=0x4
+serdes_preemphasis_lane0_xe4=0xc2f0
+serdes_preemphasis_lane1_xe4=0xc2f0
+serdes_preemphasis_lane2_xe4=0xc2f0
+serdes_preemphasis_lane3_xe4=0xc2f0
+
+# xe5 (40G)
+portmap_6=41:40
+xgxs_rx_lane_map_6=0x213
+xgxs_tx_lane_map_6=0x3021
+phy_xaui_rx_polarity_flip_6=0x3
+phy_xaui_tx_polarity_flip_6=0xb
+serdes_driver_current_lane0_xe5=0x4
+serdes_driver_current_lane1_xe5=0x4
+serdes_driver_current_lane2_xe5=0x4
+serdes_driver_current_lane3_xe5=0x4
+serdes_pre_driver_current_lane0_xe5=0x4
+serdes_pre_driver_current_lane1_xe5=0x4
+serdes_pre_driver_current_lane2_xe5=0x4
+serdes_pre_driver_current_lane3_xe5=0x4
+serdes_preemphasis_lane0_xe5=0xc6e0
+serdes_preemphasis_lane1_xe5=0xc2f0
+serdes_preemphasis_lane2_xe5=0xc2f0
+serdes_preemphasis_lane3_xe5=0xcad0
+
+# xe6 (40G)
+portmap_7=1:40
+xgxs_rx_lane_map_7=0x213
+xgxs_tx_lane_map_7=0x2031
+phy_xaui_rx_polarity_flip_7=0xe
+phy_xaui_tx_polarity_flip_7=0xd
+serdes_driver_current_lane0_xe6=0x5
+serdes_driver_current_lane1_xe6=0x5
+serdes_driver_current_lane2_xe6=0x5
+serdes_driver_current_lane3_xe6=0x5
+serdes_pre_driver_current_lane0_xe6=0x5
+serdes_pre_driver_current_lane1_xe6=0x5
+serdes_pre_driver_current_lane2_xe6=0x5
+serdes_pre_driver_current_lane3_xe6=0x5
+serdes_preemphasis_lane0_xe6=0xc6e0
+serdes_preemphasis_lane1_xe6=0xcad0
+serdes_preemphasis_lane2_xe6=0xc6e0
+serdes_preemphasis_lane3_xe6=0xcad0
+
+# xe7 (40G)
+portmap_8=5:40
+xgxs_rx_lane_map_8=0x213
+xgxs_tx_lane_map_8=0x1203
+phy_xaui_rx_polarity_flip_8=0xc
+phy_xaui_tx_polarity_flip_8=0x1
+serdes_driver_current_lane0_xe7=0x4
+serdes_driver_current_lane1_xe7=0x4
+serdes_driver_current_lane2_xe7=0x4
+serdes_driver_current_lane3_xe7=0x4
+serdes_pre_driver_current_lane0_xe7=0x4
+serdes_pre_driver_current_lane1_xe7=0x4
+serdes_pre_driver_current_lane2_xe7=0x4
+serdes_pre_driver_current_lane3_xe7=0x4
+serdes_preemphasis_lane0_xe7=0xc6e0
+serdes_preemphasis_lane1_xe7=0xc6e0
+serdes_preemphasis_lane2_xe7=0xc6e0
+serdes_preemphasis_lane3_xe7=0xc6e0
+
+# xe8 (40G)
+portmap_9=13:40
+xgxs_rx_lane_map_9=0x213
+xgxs_tx_lane_map_9=0x132
+phy_xaui_rx_polarity_flip_9=0xe
+phy_xaui_tx_polarity_flip_9=0x0
+serdes_driver_current_lane0_xe8=0x2
+serdes_driver_current_lane1_xe8=0x3
+serdes_driver_current_lane2_xe8=0x2
+serdes_driver_current_lane3_xe8=0x2
+serdes_pre_driver_current_lane0_xe8=0x2
+serdes_pre_driver_current_lane1_xe8=0x3
+serdes_pre_driver_current_lane2_xe8=0x2
+serdes_pre_driver_current_lane3_xe8=0x2
+serdes_preemphasis_lane0_xe8=0xb270
+serdes_preemphasis_lane1_xe8=0xbb10
+serdes_preemphasis_lane2_xe8=0xb720
+serdes_preemphasis_lane3_xe8=0xb720
+
+# xe9 (40G)
+portmap_10=9:40
+xgxs_rx_lane_map_10=0x3120
+xgxs_tx_lane_map_10=0x3021
+phy_xaui_rx_polarity_flip_10=0x0
+phy_xaui_tx_polarity_flip_10=0x4
+serdes_driver_current_lane0_xe9=0x3
+serdes_driver_current_lane1_xe9=0x3
+serdes_driver_current_lane2_xe9=0x3
+serdes_driver_current_lane3_xe9=0x3
+serdes_pre_driver_current_lane0_xe9=0x3
+serdes_pre_driver_current_lane1_xe9=0x3
+serdes_pre_driver_current_lane2_xe9=0x3
+serdes_pre_driver_current_lane3_xe9=0x3
+serdes_preemphasis_lane0_xe9=0xc2f0
+serdes_preemphasis_lane1_xe9=0xc6e0
+serdes_preemphasis_lane2_xe9=0xbf00
+serdes_preemphasis_lane3_xe9=0xc2f0
+
+# xe10 (40G)
+portmap_11=17:40
+xgxs_rx_lane_map_11=0x213
+xgxs_tx_lane_map_11=0x132
+phy_xaui_rx_polarity_flip_11=0xe
+phy_xaui_tx_polarity_flip_11=0x0
+serdes_driver_current_lane0_xe10=0x2
+serdes_driver_current_lane1_xe10=0x2
+serdes_driver_current_lane2_xe10=0x2
+serdes_driver_current_lane3_xe10=0x2
+serdes_pre_driver_current_lane0_xe10=0x2
+serdes_pre_driver_current_lane1_xe10=0x2
+serdes_pre_driver_current_lane2_xe10=0x2
+serdes_pre_driver_current_lane3_xe10=0x2
+serdes_preemphasis_lane0_xe10=0xb330
+serdes_preemphasis_lane1_xe10=0xbb10
+serdes_preemphasis_lane2_xe10=0xbb10
+serdes_preemphasis_lane3_xe10=0xbb10
+
+# xe11 (40G)
+portmap_12=21:40
+xgxs_rx_lane_map_12=0x123
+xgxs_tx_lane_map_12=0x1203
+phy_xaui_rx_polarity_flip_12=0xc
+phy_xaui_tx_polarity_flip_12=0xe
+serdes_driver_current_lane0_xe11=0x2
+serdes_driver_current_lane1_xe11=0x2
+serdes_driver_current_lane2_xe11=0x2
+serdes_driver_current_lane3_xe11=0x2
+serdes_pre_driver_current_lane0_xe11=0x2
+serdes_pre_driver_current_lane1_xe11=0x2
+serdes_pre_driver_current_lane2_xe11=0x2
+serdes_pre_driver_current_lane3_xe11=0x2
+serdes_preemphasis_lane0_xe11=0xb330
+serdes_preemphasis_lane1_xe11=0xb330
+serdes_preemphasis_lane2_xe11=0xb330
+serdes_preemphasis_lane3_xe11=0xb330
+
+# xe12 (40G)
+portmap_13=53:40
+xgxs_rx_lane_map_13=0x213
+xgxs_tx_lane_map_13=0x231
+phy_xaui_rx_polarity_flip_13=0x1
+phy_xaui_tx_polarity_flip_13=0x0
+serdes_driver_current_lane0_xe12=0x2
+serdes_driver_current_lane1_xe12=0x2
+serdes_driver_current_lane2_xe12=0x2
+serdes_driver_current_lane3_xe12=0x2
+serdes_pre_driver_current_lane0_xe12=0x2
+serdes_pre_driver_current_lane1_xe12=0x2
+serdes_pre_driver_current_lane2_xe12=0x2
+serdes_pre_driver_current_lane3_xe12=0x2
+serdes_preemphasis_lane0_xe12=0xaf40
+serdes_preemphasis_lane1_xe12=0xaf40
+serdes_preemphasis_lane2_xe12=0xaf40
+serdes_preemphasis_lane3_xe12=0xaf40
+
+# xe13 (40G)
+portmap_14=49:40
+xgxs_rx_lane_map_14=0x1302
+xgxs_tx_lane_map_14=0x2031
+phy_xaui_rx_polarity_flip_14=0xb
+phy_xaui_tx_polarity_flip_14=0x3
+serdes_driver_current_lane0_xe13=0x2
+serdes_driver_current_lane1_xe13=0x2
+serdes_driver_current_lane2_xe13=0x2
+serdes_driver_current_lane3_xe13=0x2
+serdes_pre_driver_current_lane0_xe13=0x2
+serdes_pre_driver_current_lane1_xe13=0x2
+serdes_pre_driver_current_lane2_xe13=0x2
+serdes_pre_driver_current_lane3_xe13=0x2
+serdes_preemphasis_lane0_xe13=0xa760
+serdes_preemphasis_lane1_xe13=0xa760
+serdes_preemphasis_lane2_xe13=0xa760
+serdes_preemphasis_lane3_xe13=0xa760
+
+# xe14 (40G)
+portmap_15=57:40
+xgxs_rx_lane_map_15=0x213
+xgxs_tx_lane_map_15=0x2031
+phy_xaui_rx_polarity_flip_15=0x1
+phy_xaui_tx_polarity_flip_15=0x0
+serdes_driver_current_lane0_xe14=0x1
+serdes_driver_current_lane1_xe14=0x1
+serdes_driver_current_lane2_xe14=0x1
+serdes_driver_current_lane3_xe14=0x1
+serdes_pre_driver_current_lane0_xe14=0x1
+serdes_pre_driver_current_lane1_xe14=0x1
+serdes_pre_driver_current_lane2_xe14=0x1
+serdes_pre_driver_current_lane3_xe14=0x1
+serdes_preemphasis_lane0_xe14=0xa760
+serdes_preemphasis_lane1_xe14=0xa760
+serdes_preemphasis_lane2_xe14=0xa760
+serdes_preemphasis_lane3_xe14=0xa760
+
+# xe15 (40G)
+portmap_16=61:40
+xgxs_rx_lane_map_16=0x132
+xgxs_tx_lane_map_16=0x213
+phy_xaui_rx_polarity_flip_16=0x0
+phy_xaui_tx_polarity_flip_16=0x0
+serdes_driver_current_lane0_xe15=0x2
+serdes_driver_current_lane1_xe15=0x2
+serdes_driver_current_lane2_xe15=0x2
+serdes_driver_current_lane3_xe15=0x2
+serdes_pre_driver_current_lane0_xe15=0x2
+serdes_pre_driver_current_lane1_xe15=0x2
+serdes_pre_driver_current_lane2_xe15=0x2
+serdes_pre_driver_current_lane3_xe15=0x2
+serdes_preemphasis_lane0_xe15=0xa760
+serdes_preemphasis_lane1_xe15=0xa760
+serdes_preemphasis_lane2_xe15=0xa760
+serdes_preemphasis_lane3_xe15=0xa760
+
+# xe16 (40G)
+portmap_17=69:40
+xgxs_rx_lane_map_17=0x213
+xgxs_tx_lane_map_17=0x2130
+phy_xaui_rx_polarity_flip_17=0x1
+phy_xaui_tx_polarity_flip_17=0xf
+serdes_driver_current_lane0_xe16=0x1
+serdes_driver_current_lane1_xe16=0x1
+serdes_driver_current_lane2_xe16=0x1
+serdes_driver_current_lane3_xe16=0x1
+serdes_pre_driver_current_lane0_xe16=0x1
+serdes_pre_driver_current_lane1_xe16=0x1
+serdes_pre_driver_current_lane2_xe16=0x1
+serdes_pre_driver_current_lane3_xe16=0x1
+serdes_preemphasis_lane0_xe16=0xa760
+serdes_preemphasis_lane1_xe16=0xa760
+serdes_preemphasis_lane2_xe16=0xa760
+serdes_preemphasis_lane3_xe16=0xa760
+
+# xe17 (40G)
+portmap_18=65:40
+xgxs_rx_lane_map_18=0x132
+xgxs_tx_lane_map_18=0x2031
+phy_xaui_rx_polarity_flip_18=0x3
+phy_xaui_tx_polarity_flip_18=0x9
+serdes_driver_current_lane0_xe17=0x1
+serdes_driver_current_lane1_xe17=0x1
+serdes_driver_current_lane2_xe17=0x1
+serdes_driver_current_lane3_xe17=0x1
+serdes_pre_driver_current_lane0_xe17=0x1
+serdes_pre_driver_current_lane1_xe17=0x1
+serdes_pre_driver_current_lane2_xe17=0x1
+serdes_pre_driver_current_lane3_xe17=0x1
+serdes_preemphasis_lane0_xe17=0xa370
+serdes_preemphasis_lane1_xe17=0xa370
+serdes_preemphasis_lane2_xe17=0xa370
+serdes_preemphasis_lane3_xe17=0xa370
+
+# xe18 (40G)
+portmap_19=73:40
+xgxs_rx_lane_map_19=0x213
+xgxs_tx_lane_map_19=0x2031
+phy_xaui_rx_polarity_flip_19=0x1
+phy_xaui_tx_polarity_flip_19=0x0
+serdes_driver_current_lane0_xe18=0x2
+serdes_driver_current_lane1_xe18=0x2
+serdes_driver_current_lane2_xe18=0x2
+serdes_driver_current_lane3_xe18=0x2
+serdes_pre_driver_current_lane0_xe18=0x2
+serdes_pre_driver_current_lane1_xe18=0x2
+serdes_pre_driver_current_lane2_xe18=0x2
+serdes_pre_driver_current_lane3_xe18=0x2
+serdes_preemphasis_lane0_xe18=0xa760
+serdes_preemphasis_lane1_xe18=0xa760
+serdes_preemphasis_lane2_xe18=0xa760
+serdes_preemphasis_lane3_xe18=0xa760
+
+# xe19 (40G)
+portmap_20=77:40
+xgxs_rx_lane_map_20=0x123
+xgxs_tx_lane_map_20=0x1203
+phy_xaui_rx_polarity_flip_20=0x3
+phy_xaui_tx_polarity_flip_20=0xe
+serdes_driver_current_lane0_xe19=0x2
+serdes_driver_current_lane1_xe19=0x2
+serdes_driver_current_lane2_xe19=0x2
+serdes_driver_current_lane3_xe19=0x2
+serdes_pre_driver_current_lane0_xe19=0x2
+serdes_pre_driver_current_lane1_xe19=0x2
+serdes_pre_driver_current_lane2_xe19=0x2
+serdes_pre_driver_current_lane3_xe19=0x2
+serdes_preemphasis_lane0_xe19=0xaf40
+serdes_preemphasis_lane1_xe19=0xaf40
+serdes_preemphasis_lane2_xe19=0xaf40
+serdes_preemphasis_lane3_xe19=0xaf40
+
+# xe20 (40G)
+portmap_21=109:40
+xgxs_rx_lane_map_21=0x132
+xgxs_tx_lane_map_21=0x132
+phy_xaui_rx_polarity_flip_21=0x8
+phy_xaui_tx_polarity_flip_21=0x0
+serdes_driver_current_lane0_xe20=0x1
+serdes_driver_current_lane1_xe20=0x1
+serdes_driver_current_lane2_xe20=0x1
+serdes_driver_current_lane3_xe20=0x2
+serdes_pre_driver_current_lane0_xe20=0x1
+serdes_pre_driver_current_lane1_xe20=0x1
+serdes_pre_driver_current_lane2_xe20=0x1
+serdes_pre_driver_current_lane3_xe20=0x2
+serdes_preemphasis_lane0_xe20=0xb330
+serdes_preemphasis_lane1_xe20=0xb330
+serdes_preemphasis_lane2_xe20=0xb330
+serdes_preemphasis_lane3_xe20=0xbff0
+
+# xe21 (40G)
+portmap_22=105:40
+xgxs_rx_lane_map_22=0x1320
+xgxs_tx_lane_map_22=0x3021
+phy_xaui_rx_polarity_flip_22=0xd
+phy_xaui_tx_polarity_flip_22=0xb
+serdes_driver_current_lane0_xe21=0x1
+serdes_driver_current_lane1_xe21=0x1
+serdes_driver_current_lane2_xe21=0x1
+serdes_driver_current_lane3_xe21=0x1
+serdes_pre_driver_current_lane0_xe21=0x1
+serdes_pre_driver_current_lane1_xe21=0x1
+serdes_pre_driver_current_lane2_xe21=0x1
+serdes_pre_driver_current_lane3_xe21=0x1
+serdes_preemphasis_lane0_xe21=0xb330
+serdes_preemphasis_lane1_xe21=0xb330
+serdes_preemphasis_lane2_xe21=0xb330
+serdes_preemphasis_lane3_xe21=0xb330
+
+# xe22 (40G)
+portmap_23=113:40
+xgxs_rx_lane_map_23=0x132
+xgxs_tx_lane_map_23=0x132
+phy_xaui_rx_polarity_flip_23=0x8
+phy_xaui_tx_polarity_flip_23=0x0
+serdes_driver_current_lane0_xe22=0x1
+serdes_driver_current_lane1_xe22=0x1
+serdes_driver_current_lane2_xe22=0x1
+serdes_driver_current_lane3_xe22=0x1
+serdes_pre_driver_current_lane0_xe22=0x1
+serdes_pre_driver_current_lane1_xe22=0x1
+serdes_pre_driver_current_lane2_xe22=0x1
+serdes_pre_driver_current_lane3_xe22=0x1
+serdes_preemphasis_lane0_xe22=0xbb10
+serdes_preemphasis_lane1_xe22=0xbb10
+serdes_preemphasis_lane2_xe22=0xbb10
+serdes_preemphasis_lane3_xe22=0xc2f0
+
+# xe23 (40G)
+portmap_24=117:40
+xgxs_rx_lane_map_24=0x231
+xgxs_tx_lane_map_24=0x1203
+phy_xaui_rx_polarity_flip_24=0x3
+phy_xaui_tx_polarity_flip_24=0xe
+serdes_driver_current_lane0_xe23=0x3
+serdes_driver_current_lane1_xe23=0x5
+serdes_driver_current_lane2_xe23=0x3
+serdes_driver_current_lane3_xe23=0x3
+serdes_pre_driver_current_lane0_xe23=0x3
+serdes_pre_driver_current_lane1_xe23=0x5
+serdes_pre_driver_current_lane2_xe23=0x3
+serdes_pre_driver_current_lane3_xe23=0x3
+serdes_preemphasis_lane0_xe23=0xc6e0
+serdes_preemphasis_lane1_xe23=0xc6e0
+serdes_preemphasis_lane2_xe23=0xc6e0
+serdes_preemphasis_lane3_xe23=0xc6e0
+
+# xe24 (40G)
+portmap_25=125:40
+xgxs_rx_lane_map_25=0x132
+xgxs_tx_lane_map_25=0x132
+phy_xaui_rx_polarity_flip_25=0x8
+phy_xaui_tx_polarity_flip_25=0x0
+serdes_driver_current_lane0_xe24=0x4
+serdes_driver_current_lane1_xe24=0x4
+serdes_driver_current_lane2_xe24=0x4
+serdes_driver_current_lane3_xe24=0x4
+serdes_pre_driver_current_lane0_xe24=0x4
+serdes_pre_driver_current_lane1_xe24=0x4
+serdes_pre_driver_current_lane2_xe24=0x4
+serdes_pre_driver_current_lane3_xe24=0x4
+serdes_preemphasis_lane0_xe24=0xc6e0
+serdes_preemphasis_lane1_xe24=0xc6e0
+serdes_preemphasis_lane2_xe24=0xc6e0
+serdes_preemphasis_lane3_xe24=0xcec0
+
+# xe25 (40G)
+portmap_26=121:40
+xgxs_rx_lane_map_26=0x1320
+xgxs_tx_lane_map_26=0x3021
+phy_xaui_rx_polarity_flip_26=0xd
+phy_xaui_tx_polarity_flip_26=0xb
+serdes_driver_current_lane0_xe25=0x4
+serdes_driver_current_lane1_xe25=0x4
+serdes_driver_current_lane2_xe25=0x4
+serdes_driver_current_lane3_xe25=0x4
+serdes_pre_driver_current_lane0_xe25=0x4
+serdes_pre_driver_current_lane1_xe25=0x4
+serdes_pre_driver_current_lane2_xe25=0x4
+serdes_pre_driver_current_lane3_xe25=0x4
+serdes_preemphasis_lane0_xe25=0xc6e0
+serdes_preemphasis_lane1_xe25=0xc6e0
+serdes_preemphasis_lane2_xe25=0xc6e0
+serdes_preemphasis_lane3_xe25=0xc6e0
+
+# xe26 (40G)
+portmap_27=81:40
+xgxs_rx_lane_map_27=0x1320
+xgxs_tx_lane_map_27=0x2031
+phy_xaui_rx_polarity_flip_27=0x1
+phy_xaui_tx_polarity_flip_27=0x2
+serdes_driver_current_lane0_xe26=0x2
+serdes_driver_current_lane1_xe26=0x2
+serdes_driver_current_lane2_xe26=0x2
+serdes_driver_current_lane3_xe26=0x2
+serdes_pre_driver_current_lane0_xe26=0x2
+serdes_pre_driver_current_lane1_xe26=0x2
+serdes_pre_driver_current_lane2_xe26=0x2
+serdes_pre_driver_current_lane3_xe26=0x2
+serdes_preemphasis_lane0_xe26=0xbb10
+serdes_preemphasis_lane1_xe26=0xbb10
+serdes_preemphasis_lane2_xe26=0xbf00
+serdes_preemphasis_lane3_xe26=0xbb10
+
+# xe27 (40G)
+portmap_28=85:40
+xgxs_rx_lane_map_28=0x213
+xgxs_tx_lane_map_28=0x1203
+phy_xaui_rx_polarity_flip_28=0xc
+phy_xaui_tx_polarity_flip_28=0xe
+serdes_driver_current_lane0_xe27=0x4
+serdes_driver_current_lane1_xe27=0x5
+serdes_driver_current_lane2_xe27=0x4
+serdes_driver_current_lane3_xe27=0x5
+serdes_pre_driver_current_lane0_xe27=0x4
+serdes_pre_driver_current_lane1_xe27=0x5
+serdes_pre_driver_current_lane2_xe27=0x4
+serdes_pre_driver_current_lane3_xe27=0x5
+serdes_preemphasis_lane0_xe27=0xc2f0
+serdes_preemphasis_lane1_xe27=0xc6e0
+serdes_preemphasis_lane2_xe27=0xc6e0
+serdes_preemphasis_lane3_xe27=0xc6e0
+
+# xe28 (40G)
+portmap_29=93:40
+xgxs_rx_lane_map_29=0x1320
+xgxs_tx_lane_map_29=0x2031
+phy_xaui_rx_polarity_flip_29=0x1
+phy_xaui_tx_polarity_flip_29=0x2
+serdes_driver_current_lane0_xe28=0x4
+serdes_driver_current_lane1_xe28=0x4
+serdes_driver_current_lane2_xe28=0x4
+serdes_driver_current_lane3_xe28=0x4
+serdes_pre_driver_current_lane0_xe28=0x4
+serdes_pre_driver_current_lane1_xe28=0x4
+serdes_pre_driver_current_lane2_xe28=0x4
+serdes_pre_driver_current_lane3_xe28=0x4
+serdes_preemphasis_lane0_xe28=0xc2f0
+serdes_preemphasis_lane1_xe28=0xc2f0
+serdes_preemphasis_lane2_xe28=0xc2f0
+serdes_preemphasis_lane3_xe28=0xc2f0
+
+# xe29 (40G)
+portmap_30=89:40
+xgxs_rx_lane_map_30=0x1320
+xgxs_tx_lane_map_30=0x3021
+phy_xaui_rx_polarity_flip_30=0x2
+phy_xaui_tx_polarity_flip_30=0xb
+serdes_driver_current_lane0_xe29=0x4
+serdes_driver_current_lane1_xe29=0x4
+serdes_driver_current_lane2_xe29=0x4
+serdes_driver_current_lane3_xe29=0x4
+serdes_pre_driver_current_lane0_xe29=0x4
+serdes_pre_driver_current_lane1_xe29=0x4
+serdes_pre_driver_current_lane2_xe29=0x4
+serdes_pre_driver_current_lane3_xe29=0x4
+serdes_preemphasis_lane0_xe29=0xcad0
+serdes_preemphasis_lane1_xe29=0xc6e0
+serdes_preemphasis_lane2_xe29=0xc6e0
+serdes_preemphasis_lane3_xe29=0xc6e0
+
+# xe30 (40G)
+portmap_31=101:40
+xgxs_rx_lane_map_31=0x1320
+xgxs_tx_lane_map_31=0x1203
+phy_xaui_rx_polarity_flip_31=0x1
+phy_xaui_tx_polarity_flip_31=0x6
+serdes_driver_current_lane0_xe30=0x6
+serdes_driver_current_lane1_xe30=0x6
+serdes_driver_current_lane2_xe30=0x6
+serdes_driver_current_lane3_xe30=0x7
+serdes_pre_driver_current_lane0_xe30=0x6
+serdes_pre_driver_current_lane1_xe30=0x6
+serdes_pre_driver_current_lane2_xe30=0x6
+serdes_pre_driver_current_lane3_xe30=0x7
+serdes_preemphasis_lane0_xe30=0xcec0
+serdes_preemphasis_lane1_xe30=0xcec0
+serdes_preemphasis_lane2_xe30=0xcad0
+serdes_preemphasis_lane3_xe30=0xc6e0
+
+# xe31 (40G)
+portmap_32=97:40
+xgxs_rx_lane_map_32=0x213
+xgxs_tx_lane_map_32=0x2031
+phy_xaui_rx_polarity_flip_32=0xc
+phy_xaui_tx_polarity_flip_32=0x3
+serdes_driver_current_lane0_xe31=0x5
+serdes_driver_current_lane1_xe31=0x5
+serdes_driver_current_lane2_xe31=0x5
+serdes_driver_current_lane3_xe31=0x5
+serdes_pre_driver_current_lane0_xe31=0x5
+serdes_pre_driver_current_lane1_xe31=0x5
+serdes_pre_driver_current_lane2_xe31=0x5
+serdes_pre_driver_current_lane3_xe31=0x5
+serdes_preemphasis_lane0_xe31=0xcad0
+serdes_preemphasis_lane1_xe31=0xcad0
+serdes_preemphasis_lane2_xe31=0xcad0
+serdes_preemphasis_lane3_xe31=0xcad0
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/buffers.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/buffers.json.j2
new file mode 100644
index 000000000000..b67cf577ab75
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/buffers.json.j2
@@ -0,0 +1,3 @@
+{%- set default_topo = 't1' %}
+{%- include 'buffers_config.j2' %}
+
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/buffers_defaults_def.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/buffers_defaults_def.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/buffers_defaults_def.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/buffers_defaults_t0.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/buffers_defaults_t0.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/buffers_defaults_t0.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/buffers_defaults_t1.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/buffers_defaults_t1.j2
new file mode 100644
index 000000000000..38e34eb571e8
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/buffers_defaults_t1.j2
@@ -0,0 +1,45 @@
+{%- set default_cable = '300m' %}
+
+{%- macro generate_port_lists(PORT_ALL) %}
+ {# Generate list of ports #}
+ {% for port_idx in range(0,32) %}
+ {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %}
+ {% endfor %}
+{%- endmacro %}
+
+{%- macro generate_buffer_pool_and_profiles() %}
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "12766208",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "7326924",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"12766208"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+{%- endmacro %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/lanemap.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/lanemap.ini
new file mode 100644
index 000000000000..36278a01778c
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/lanemap.ini
@@ -0,0 +1,32 @@
+eth1:25,26,27,28
+eth2:29,30,31,32
+eth3:33,34,35,36
+eth4:37,38,39,40
+eth5:45,46,47,48
+eth6:41,42,43,44
+eth7:1,2,3,4
+eth8:5,6,7,8
+eth9:13,14,15,16
+eth10:9,10,11,12
+eth11:17,18,19,20
+eth12:21,22,23,24
+eth13:53,54,55,56
+eth14:49,50,51,52
+eth15:57,58,59,60
+eth16:61,62,63,64
+eth17:69,70,71,72
+eth18:65,66,67,68
+eth19:73,74,75,76
+eth20:77,78,79,80
+eth21:109,110,111,112
+eth22:105,106,107,108
+eth23:113,114,115,116
+eth24:117,118,119,120
+eth25:125,126,127,128
+eth26:121,122,123,124
+eth27:81,82,83,84
+eth28:85,86,87,88
+eth29:93,94,95,96
+eth30:89,90,91,92
+eth31:101,102,103,104
+eth32:97,98,99,100
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/pg_profile_lookup.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/pg_profile_lookup.ini
new file mode 100644
index 000000000000..9f2eacb6fc42
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/pg_profile_lookup.ini
@@ -0,0 +1,17 @@
+# PG lossless profiles.
+# speed cable size xon xoff threshold xon_offset
+ 10000 5m 56368 18432 55120 -3 2496
+ 25000 5m 56368 18432 55120 -3 2496
+ 40000 5m 56368 18432 55120 -3 2496
+ 50000 5m 56368 18432 55120 -3 2496
+ 100000 5m 56368 18432 55120 -3 2496
+ 10000 40m 56368 18432 55120 -3 2496
+ 25000 40m 56368 18432 55120 -3 2496
+ 40000 40m 56368 18432 55120 -3 2496
+ 50000 40m 56368 18432 55120 -3 2496
+ 100000 40m 56368 18432 55120 -3 2496
+ 10000 300m 56368 18432 55120 -3 2496
+ 25000 300m 56368 18432 55120 -3 2496
+ 40000 300m 56368 18432 55120 -3 2496
+ 50000 300m 56368 18432 55120 -3 2496
+ 100000 300m 56368 18432 55120 -3 2496
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/port_config.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/port_config.ini
new file mode 100644
index 000000000000..95cf5eec9e4e
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/port_config.ini
@@ -0,0 +1,33 @@
+# name lanes alias index speed
+Ethernet0 25,26,27,28 fortyGigE0/0 0 40000
+Ethernet4 29,30,31,32 fortyGigE0/4 1 40000
+Ethernet8 33,34,35,36 fortyGigE0/8 2 40000
+Ethernet12 37,38,39,40 fortyGigE0/12 3 40000
+Ethernet16 45,46,47,48 fortyGigE0/16 4 40000
+Ethernet20 41,42,43,44 fortyGigE0/20 5 40000
+Ethernet24 1,2,3,4 fortyGigE0/24 6 40000
+Ethernet28 5,6,7,8 fortyGigE0/28 7 40000
+Ethernet32 13,14,15,16 fortyGigE0/32 8 40000
+Ethernet36 9,10,11,12 fortyGigE0/36 9 40000
+Ethernet40 17,18,19,20 fortyGigE0/40 10 40000
+Ethernet44 21,22,23,24 fortyGigE0/44 11 40000
+Ethernet48 53,54,55,56 fortyGigE0/48 12 40000
+Ethernet52 49,50,51,52 fortyGigE0/52 13 40000
+Ethernet56 57,58,59,60 fortyGigE0/56 14 40000
+Ethernet60 61,62,63,64 fortyGigE0/60 15 40000
+Ethernet64 69,70,71,72 fortyGigE0/64 16 40000
+Ethernet68 65,66,67,68 fortyGigE0/68 17 40000
+Ethernet72 73,74,75,76 fortyGigE0/72 18 40000
+Ethernet76 77,78,79,80 fortyGigE0/76 19 40000
+Ethernet80 109,110,111,112 fortyGigE0/80 20 40000
+Ethernet84 105,106,107,108 fortyGigE0/84 21 40000
+Ethernet88 113,114,115,116 fortyGigE0/88 22 40000
+Ethernet92 117,118,119,120 fortyGigE0/92 23 40000
+Ethernet96 125,126,127,128 fortyGigE0/96 24 40000
+Ethernet100 121,122,123,124 fortyGigE0/100 25 40000
+Ethernet104 81,82,83,84 fortyGigE0/104 26 40000
+Ethernet108 85,86,87,88 fortyGigE0/108 27 40000
+Ethernet112 93,94,95,96 fortyGigE0/112 28 40000
+Ethernet116 89,90,91,92 fortyGigE0/116 29 40000
+Ethernet120 101,102,103,104 fortyGigE0/120 30 40000
+Ethernet124 97,98,99,100 fortyGigE0/124 31 40000
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/qos.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/qos.json.j2
new file mode 100644
index 000000000000..3e548325ea30
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/qos.json.j2
@@ -0,0 +1 @@
+{%- include 'qos_config.j2' %}
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/sai.profile b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/sai.profile
new file mode 100644
index 000000000000..bfc466f27e54
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/sai.profile
@@ -0,0 +1,5 @@
+SAI_WARM_BOOT_READ_FILE=/var/cache/sai_warmboot.bin
+SAI_WARM_BOOT_WRITE_FILE=/var/cache/sai_warmboot.bin
+SAI_VS_SWITCH_TYPE=SAI_VS_SWITCH_TYPE_BCM56850
+SAI_VS_HOSTIF_USE_TAP_DEVICE=true
+SAI_VS_INTERFACE_LANE_MAP_FILE=/usr/share/sonic/hwsku/lanemap.ini
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/td2-s6000-32x40G.config.bcm b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/td2-s6000-32x40G.config.bcm
new file mode 100644
index 000000000000..4c94db7107c7
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/td2-s6000-32x40G.config.bcm
@@ -0,0 +1,646 @@
+# Old LPM only configuration
+# l2_mem_entries=163840
+# l3_mem_entries=90112
+# l3_alpm_enable=0
+# ipv6_lpm_128b_enable=0
+#
+# ALPM enable
+l3_alpm_enable=2
+ipv6_lpm_128b_enable=1
+l2_mem_entries=32768
+l3_mem_entries=16384
+
+# From old config file
+os=unix
+higig2_hdr_mode=1
+
+# Parity
+parity_correction=1
+parity_enable=1
+stat_if_parity_enable=0
+
+#
+bcm_num_cos=8
+bcm_stat_interval=2000000
+l2xmsg_hostbuf_size=8192
+l2xmsg_mode=1
+lls_num_l2uc=12
+max_vp_lags=0
+miim_intr_enable=0
+mmu_lossless=0
+module_64ports=0
+schan_intr_enable=0
+stable_size=0x2000000
+tdma_timeout_usec=5000000
+
+pbmp_oversubscribe=0x000007fffffffffffffffffffffffffe
+pbmp_xport_xe=0x000007fffffffffffffffffffffffffe
+
+# Ports configuration
+# xe0 (40G)
+portmap_1=25:40
+xgxs_rx_lane_map_1=0x213
+xgxs_tx_lane_map_1=0x2031
+phy_xaui_rx_polarity_flip_1=0xe
+phy_xaui_tx_polarity_flip_1=0x2
+serdes_driver_current_lane0_xe0=0x5
+serdes_driver_current_lane1_xe0=0x5
+serdes_driver_current_lane2_xe0=0x5
+serdes_driver_current_lane3_xe0=0x5
+serdes_pre_driver_current_lane0_xe0=0x5
+serdes_pre_driver_current_lane1_xe0=0x5
+serdes_pre_driver_current_lane2_xe0=0x5
+serdes_pre_driver_current_lane3_xe0=0x5
+serdes_preemphasis_lane0_xe0=0xcad0
+serdes_preemphasis_lane1_xe0=0xc6e0
+serdes_preemphasis_lane2_xe0=0xc6e0
+serdes_preemphasis_lane3_xe0=0xd2b0
+
+# xe1 (40G)
+portmap_2=29:40
+xgxs_rx_lane_map_2=0x213
+xgxs_tx_lane_map_2=0x213
+phy_xaui_rx_polarity_flip_2=0xc
+phy_xaui_tx_polarity_flip_2=0x9
+serdes_driver_current_lane0_xe1=0x6
+serdes_driver_current_lane1_xe1=0x7
+serdes_driver_current_lane2_xe1=0x6
+serdes_driver_current_lane3_xe1=0x6
+serdes_pre_driver_current_lane0_xe1=0x6
+serdes_pre_driver_current_lane1_xe1=0x7
+serdes_pre_driver_current_lane2_xe1=0x6
+serdes_pre_driver_current_lane3_xe1=0x6
+serdes_preemphasis_lane0_xe1=0xc2f0
+serdes_preemphasis_lane1_xe1=0xd2b0
+serdes_preemphasis_lane2_xe1=0xc6e0
+serdes_preemphasis_lane3_xe1=0xc2f0
+
+# xe2 (40G)
+portmap_3=33:40
+xgxs_rx_lane_map_3=0x213
+xgxs_tx_lane_map_3=0x132
+phy_xaui_rx_polarity_flip_3=0xe
+phy_xaui_tx_polarity_flip_3=0x2
+serdes_driver_current_lane0_xe2=0x4
+serdes_driver_current_lane1_xe2=0x4
+serdes_driver_current_lane2_xe2=0x4
+serdes_driver_current_lane3_xe2=0x4
+serdes_pre_driver_current_lane0_xe2=0x4
+serdes_pre_driver_current_lane1_xe2=0x4
+serdes_pre_driver_current_lane2_xe2=0x4
+serdes_pre_driver_current_lane3_xe2=0x4
+serdes_preemphasis_lane0_xe2=0xc6e0
+serdes_preemphasis_lane1_xe2=0xc6e0
+serdes_preemphasis_lane2_xe2=0xc6e0
+serdes_preemphasis_lane3_xe2=0xc6e0
+
+# xe3 (40G)
+portmap_4=37:40
+xgxs_rx_lane_map_4=0x213
+xgxs_tx_lane_map_4=0x1203
+phy_xaui_rx_polarity_flip_4=0x3
+phy_xaui_tx_polarity_flip_4=0xe
+serdes_driver_current_lane0_xe3=0x4
+serdes_driver_current_lane1_xe3=0x4
+serdes_driver_current_lane2_xe3=0x4
+serdes_driver_current_lane3_xe3=0x4
+serdes_pre_driver_current_lane0_xe3=0x4
+serdes_pre_driver_current_lane1_xe3=0x4
+serdes_pre_driver_current_lane2_xe3=0x4
+serdes_pre_driver_current_lane3_xe3=0x4
+serdes_preemphasis_lane0_xe3=0xcad0
+serdes_preemphasis_lane1_xe3=0xcad0
+serdes_preemphasis_lane2_xe3=0xc2f0
+serdes_preemphasis_lane3_xe3=0xc2f0
+
+# xe4 (40G)
+portmap_5=45:40
+xgxs_rx_lane_map_5=0x213
+xgxs_tx_lane_map_5=0x213
+phy_xaui_rx_polarity_flip_5=0xe
+phy_xaui_tx_polarity_flip_5=0x8
+serdes_driver_current_lane0_xe4=0x4
+serdes_driver_current_lane1_xe4=0x4
+serdes_driver_current_lane2_xe4=0x4
+serdes_driver_current_lane3_xe4=0x4
+serdes_pre_driver_current_lane0_xe4=0x4
+serdes_pre_driver_current_lane1_xe4=0x4
+serdes_pre_driver_current_lane2_xe4=0x4
+serdes_pre_driver_current_lane3_xe4=0x4
+serdes_preemphasis_lane0_xe4=0xc2f0
+serdes_preemphasis_lane1_xe4=0xc2f0
+serdes_preemphasis_lane2_xe4=0xc2f0
+serdes_preemphasis_lane3_xe4=0xc2f0
+
+# xe5 (40G)
+portmap_6=41:40
+xgxs_rx_lane_map_6=0x213
+xgxs_tx_lane_map_6=0x3021
+phy_xaui_rx_polarity_flip_6=0x3
+phy_xaui_tx_polarity_flip_6=0xb
+serdes_driver_current_lane0_xe5=0x4
+serdes_driver_current_lane1_xe5=0x4
+serdes_driver_current_lane2_xe5=0x4
+serdes_driver_current_lane3_xe5=0x4
+serdes_pre_driver_current_lane0_xe5=0x4
+serdes_pre_driver_current_lane1_xe5=0x4
+serdes_pre_driver_current_lane2_xe5=0x4
+serdes_pre_driver_current_lane3_xe5=0x4
+serdes_preemphasis_lane0_xe5=0xc6e0
+serdes_preemphasis_lane1_xe5=0xc2f0
+serdes_preemphasis_lane2_xe5=0xc2f0
+serdes_preemphasis_lane3_xe5=0xcad0
+
+# xe6 (40G)
+portmap_7=1:40
+xgxs_rx_lane_map_7=0x213
+xgxs_tx_lane_map_7=0x2031
+phy_xaui_rx_polarity_flip_7=0xe
+phy_xaui_tx_polarity_flip_7=0xd
+serdes_driver_current_lane0_xe6=0x5
+serdes_driver_current_lane1_xe6=0x5
+serdes_driver_current_lane2_xe6=0x5
+serdes_driver_current_lane3_xe6=0x5
+serdes_pre_driver_current_lane0_xe6=0x5
+serdes_pre_driver_current_lane1_xe6=0x5
+serdes_pre_driver_current_lane2_xe6=0x5
+serdes_pre_driver_current_lane3_xe6=0x5
+serdes_preemphasis_lane0_xe6=0xc6e0
+serdes_preemphasis_lane1_xe6=0xcad0
+serdes_preemphasis_lane2_xe6=0xc6e0
+serdes_preemphasis_lane3_xe6=0xcad0
+
+# xe7 (40G)
+portmap_8=5:40
+xgxs_rx_lane_map_8=0x213
+xgxs_tx_lane_map_8=0x1203
+phy_xaui_rx_polarity_flip_8=0xc
+phy_xaui_tx_polarity_flip_8=0x1
+serdes_driver_current_lane0_xe7=0x4
+serdes_driver_current_lane1_xe7=0x4
+serdes_driver_current_lane2_xe7=0x4
+serdes_driver_current_lane3_xe7=0x4
+serdes_pre_driver_current_lane0_xe7=0x4
+serdes_pre_driver_current_lane1_xe7=0x4
+serdes_pre_driver_current_lane2_xe7=0x4
+serdes_pre_driver_current_lane3_xe7=0x4
+serdes_preemphasis_lane0_xe7=0xc6e0
+serdes_preemphasis_lane1_xe7=0xc6e0
+serdes_preemphasis_lane2_xe7=0xc6e0
+serdes_preemphasis_lane3_xe7=0xc6e0
+
+# xe8 (40G)
+portmap_9=13:40
+xgxs_rx_lane_map_9=0x213
+xgxs_tx_lane_map_9=0x132
+phy_xaui_rx_polarity_flip_9=0xe
+phy_xaui_tx_polarity_flip_9=0x0
+serdes_driver_current_lane0_xe8=0x2
+serdes_driver_current_lane1_xe8=0x3
+serdes_driver_current_lane2_xe8=0x2
+serdes_driver_current_lane3_xe8=0x2
+serdes_pre_driver_current_lane0_xe8=0x2
+serdes_pre_driver_current_lane1_xe8=0x3
+serdes_pre_driver_current_lane2_xe8=0x2
+serdes_pre_driver_current_lane3_xe8=0x2
+serdes_preemphasis_lane0_xe8=0xb270
+serdes_preemphasis_lane1_xe8=0xbb10
+serdes_preemphasis_lane2_xe8=0xb720
+serdes_preemphasis_lane3_xe8=0xb720
+
+# xe9 (40G)
+portmap_10=9:40
+xgxs_rx_lane_map_10=0x3120
+xgxs_tx_lane_map_10=0x3021
+phy_xaui_rx_polarity_flip_10=0x0
+phy_xaui_tx_polarity_flip_10=0x4
+serdes_driver_current_lane0_xe9=0x3
+serdes_driver_current_lane1_xe9=0x3
+serdes_driver_current_lane2_xe9=0x3
+serdes_driver_current_lane3_xe9=0x3
+serdes_pre_driver_current_lane0_xe9=0x3
+serdes_pre_driver_current_lane1_xe9=0x3
+serdes_pre_driver_current_lane2_xe9=0x3
+serdes_pre_driver_current_lane3_xe9=0x3
+serdes_preemphasis_lane0_xe9=0xc2f0
+serdes_preemphasis_lane1_xe9=0xc6e0
+serdes_preemphasis_lane2_xe9=0xbf00
+serdes_preemphasis_lane3_xe9=0xc2f0
+
+# xe10 (40G)
+portmap_11=17:40
+xgxs_rx_lane_map_11=0x213
+xgxs_tx_lane_map_11=0x132
+phy_xaui_rx_polarity_flip_11=0xe
+phy_xaui_tx_polarity_flip_11=0x0
+serdes_driver_current_lane0_xe10=0x2
+serdes_driver_current_lane1_xe10=0x2
+serdes_driver_current_lane2_xe10=0x2
+serdes_driver_current_lane3_xe10=0x2
+serdes_pre_driver_current_lane0_xe10=0x2
+serdes_pre_driver_current_lane1_xe10=0x2
+serdes_pre_driver_current_lane2_xe10=0x2
+serdes_pre_driver_current_lane3_xe10=0x2
+serdes_preemphasis_lane0_xe10=0xb330
+serdes_preemphasis_lane1_xe10=0xbb10
+serdes_preemphasis_lane2_xe10=0xbb10
+serdes_preemphasis_lane3_xe10=0xbb10
+
+# xe11 (40G)
+portmap_12=21:40
+xgxs_rx_lane_map_12=0x123
+xgxs_tx_lane_map_12=0x1203
+phy_xaui_rx_polarity_flip_12=0xc
+phy_xaui_tx_polarity_flip_12=0xe
+serdes_driver_current_lane0_xe11=0x2
+serdes_driver_current_lane1_xe11=0x2
+serdes_driver_current_lane2_xe11=0x2
+serdes_driver_current_lane3_xe11=0x2
+serdes_pre_driver_current_lane0_xe11=0x2
+serdes_pre_driver_current_lane1_xe11=0x2
+serdes_pre_driver_current_lane2_xe11=0x2
+serdes_pre_driver_current_lane3_xe11=0x2
+serdes_preemphasis_lane0_xe11=0xb330
+serdes_preemphasis_lane1_xe11=0xb330
+serdes_preemphasis_lane2_xe11=0xb330
+serdes_preemphasis_lane3_xe11=0xb330
+
+# xe12 (40G)
+portmap_13=53:40
+xgxs_rx_lane_map_13=0x213
+xgxs_tx_lane_map_13=0x231
+phy_xaui_rx_polarity_flip_13=0x1
+phy_xaui_tx_polarity_flip_13=0x0
+serdes_driver_current_lane0_xe12=0x2
+serdes_driver_current_lane1_xe12=0x2
+serdes_driver_current_lane2_xe12=0x2
+serdes_driver_current_lane3_xe12=0x2
+serdes_pre_driver_current_lane0_xe12=0x2
+serdes_pre_driver_current_lane1_xe12=0x2
+serdes_pre_driver_current_lane2_xe12=0x2
+serdes_pre_driver_current_lane3_xe12=0x2
+serdes_preemphasis_lane0_xe12=0xaf40
+serdes_preemphasis_lane1_xe12=0xaf40
+serdes_preemphasis_lane2_xe12=0xaf40
+serdes_preemphasis_lane3_xe12=0xaf40
+
+# xe13 (40G)
+portmap_14=49:40
+xgxs_rx_lane_map_14=0x1302
+xgxs_tx_lane_map_14=0x2031
+phy_xaui_rx_polarity_flip_14=0xb
+phy_xaui_tx_polarity_flip_14=0x3
+serdes_driver_current_lane0_xe13=0x2
+serdes_driver_current_lane1_xe13=0x2
+serdes_driver_current_lane2_xe13=0x2
+serdes_driver_current_lane3_xe13=0x2
+serdes_pre_driver_current_lane0_xe13=0x2
+serdes_pre_driver_current_lane1_xe13=0x2
+serdes_pre_driver_current_lane2_xe13=0x2
+serdes_pre_driver_current_lane3_xe13=0x2
+serdes_preemphasis_lane0_xe13=0xa760
+serdes_preemphasis_lane1_xe13=0xa760
+serdes_preemphasis_lane2_xe13=0xa760
+serdes_preemphasis_lane3_xe13=0xa760
+
+# xe14 (40G)
+portmap_15=57:40
+xgxs_rx_lane_map_15=0x213
+xgxs_tx_lane_map_15=0x2031
+phy_xaui_rx_polarity_flip_15=0x1
+phy_xaui_tx_polarity_flip_15=0x0
+serdes_driver_current_lane0_xe14=0x1
+serdes_driver_current_lane1_xe14=0x1
+serdes_driver_current_lane2_xe14=0x1
+serdes_driver_current_lane3_xe14=0x1
+serdes_pre_driver_current_lane0_xe14=0x1
+serdes_pre_driver_current_lane1_xe14=0x1
+serdes_pre_driver_current_lane2_xe14=0x1
+serdes_pre_driver_current_lane3_xe14=0x1
+serdes_preemphasis_lane0_xe14=0xa760
+serdes_preemphasis_lane1_xe14=0xa760
+serdes_preemphasis_lane2_xe14=0xa760
+serdes_preemphasis_lane3_xe14=0xa760
+
+# xe15 (40G)
+portmap_16=61:40
+xgxs_rx_lane_map_16=0x132
+xgxs_tx_lane_map_16=0x213
+phy_xaui_rx_polarity_flip_16=0x0
+phy_xaui_tx_polarity_flip_16=0x0
+serdes_driver_current_lane0_xe15=0x2
+serdes_driver_current_lane1_xe15=0x2
+serdes_driver_current_lane2_xe15=0x2
+serdes_driver_current_lane3_xe15=0x2
+serdes_pre_driver_current_lane0_xe15=0x2
+serdes_pre_driver_current_lane1_xe15=0x2
+serdes_pre_driver_current_lane2_xe15=0x2
+serdes_pre_driver_current_lane3_xe15=0x2
+serdes_preemphasis_lane0_xe15=0xa760
+serdes_preemphasis_lane1_xe15=0xa760
+serdes_preemphasis_lane2_xe15=0xa760
+serdes_preemphasis_lane3_xe15=0xa760
+
+# xe16 (40G)
+portmap_17=69:40
+xgxs_rx_lane_map_17=0x213
+xgxs_tx_lane_map_17=0x2130
+phy_xaui_rx_polarity_flip_17=0x1
+phy_xaui_tx_polarity_flip_17=0xf
+serdes_driver_current_lane0_xe16=0x1
+serdes_driver_current_lane1_xe16=0x1
+serdes_driver_current_lane2_xe16=0x1
+serdes_driver_current_lane3_xe16=0x1
+serdes_pre_driver_current_lane0_xe16=0x1
+serdes_pre_driver_current_lane1_xe16=0x1
+serdes_pre_driver_current_lane2_xe16=0x1
+serdes_pre_driver_current_lane3_xe16=0x1
+serdes_preemphasis_lane0_xe16=0xa760
+serdes_preemphasis_lane1_xe16=0xa760
+serdes_preemphasis_lane2_xe16=0xa760
+serdes_preemphasis_lane3_xe16=0xa760
+
+# xe17 (40G)
+portmap_18=65:40
+xgxs_rx_lane_map_18=0x132
+xgxs_tx_lane_map_18=0x2031
+phy_xaui_rx_polarity_flip_18=0x3
+phy_xaui_tx_polarity_flip_18=0x9
+serdes_driver_current_lane0_xe17=0x1
+serdes_driver_current_lane1_xe17=0x1
+serdes_driver_current_lane2_xe17=0x1
+serdes_driver_current_lane3_xe17=0x1
+serdes_pre_driver_current_lane0_xe17=0x1
+serdes_pre_driver_current_lane1_xe17=0x1
+serdes_pre_driver_current_lane2_xe17=0x1
+serdes_pre_driver_current_lane3_xe17=0x1
+serdes_preemphasis_lane0_xe17=0xa370
+serdes_preemphasis_lane1_xe17=0xa370
+serdes_preemphasis_lane2_xe17=0xa370
+serdes_preemphasis_lane3_xe17=0xa370
+
+# xe18 (40G)
+portmap_19=73:40
+xgxs_rx_lane_map_19=0x213
+xgxs_tx_lane_map_19=0x2031
+phy_xaui_rx_polarity_flip_19=0x1
+phy_xaui_tx_polarity_flip_19=0x0
+serdes_driver_current_lane0_xe18=0x2
+serdes_driver_current_lane1_xe18=0x2
+serdes_driver_current_lane2_xe18=0x2
+serdes_driver_current_lane3_xe18=0x2
+serdes_pre_driver_current_lane0_xe18=0x2
+serdes_pre_driver_current_lane1_xe18=0x2
+serdes_pre_driver_current_lane2_xe18=0x2
+serdes_pre_driver_current_lane3_xe18=0x2
+serdes_preemphasis_lane0_xe18=0xa760
+serdes_preemphasis_lane1_xe18=0xa760
+serdes_preemphasis_lane2_xe18=0xa760
+serdes_preemphasis_lane3_xe18=0xa760
+
+# xe19 (40G)
+portmap_20=77:40
+xgxs_rx_lane_map_20=0x123
+xgxs_tx_lane_map_20=0x1203
+phy_xaui_rx_polarity_flip_20=0x3
+phy_xaui_tx_polarity_flip_20=0xe
+serdes_driver_current_lane0_xe19=0x2
+serdes_driver_current_lane1_xe19=0x2
+serdes_driver_current_lane2_xe19=0x2
+serdes_driver_current_lane3_xe19=0x2
+serdes_pre_driver_current_lane0_xe19=0x2
+serdes_pre_driver_current_lane1_xe19=0x2
+serdes_pre_driver_current_lane2_xe19=0x2
+serdes_pre_driver_current_lane3_xe19=0x2
+serdes_preemphasis_lane0_xe19=0xaf40
+serdes_preemphasis_lane1_xe19=0xaf40
+serdes_preemphasis_lane2_xe19=0xaf40
+serdes_preemphasis_lane3_xe19=0xaf40
+
+# xe20 (40G)
+portmap_21=109:40
+xgxs_rx_lane_map_21=0x132
+xgxs_tx_lane_map_21=0x132
+phy_xaui_rx_polarity_flip_21=0x8
+phy_xaui_tx_polarity_flip_21=0x0
+serdes_driver_current_lane0_xe20=0x1
+serdes_driver_current_lane1_xe20=0x1
+serdes_driver_current_lane2_xe20=0x1
+serdes_driver_current_lane3_xe20=0x2
+serdes_pre_driver_current_lane0_xe20=0x1
+serdes_pre_driver_current_lane1_xe20=0x1
+serdes_pre_driver_current_lane2_xe20=0x1
+serdes_pre_driver_current_lane3_xe20=0x2
+serdes_preemphasis_lane0_xe20=0xb330
+serdes_preemphasis_lane1_xe20=0xb330
+serdes_preemphasis_lane2_xe20=0xb330
+serdes_preemphasis_lane3_xe20=0xbff0
+
+# xe21 (40G)
+portmap_22=105:40
+xgxs_rx_lane_map_22=0x1320
+xgxs_tx_lane_map_22=0x3021
+phy_xaui_rx_polarity_flip_22=0xd
+phy_xaui_tx_polarity_flip_22=0xb
+serdes_driver_current_lane0_xe21=0x1
+serdes_driver_current_lane1_xe21=0x1
+serdes_driver_current_lane2_xe21=0x1
+serdes_driver_current_lane3_xe21=0x1
+serdes_pre_driver_current_lane0_xe21=0x1
+serdes_pre_driver_current_lane1_xe21=0x1
+serdes_pre_driver_current_lane2_xe21=0x1
+serdes_pre_driver_current_lane3_xe21=0x1
+serdes_preemphasis_lane0_xe21=0xb330
+serdes_preemphasis_lane1_xe21=0xb330
+serdes_preemphasis_lane2_xe21=0xb330
+serdes_preemphasis_lane3_xe21=0xb330
+
+# xe22 (40G)
+portmap_23=113:40
+xgxs_rx_lane_map_23=0x132
+xgxs_tx_lane_map_23=0x132
+phy_xaui_rx_polarity_flip_23=0x8
+phy_xaui_tx_polarity_flip_23=0x0
+serdes_driver_current_lane0_xe22=0x1
+serdes_driver_current_lane1_xe22=0x1
+serdes_driver_current_lane2_xe22=0x1
+serdes_driver_current_lane3_xe22=0x1
+serdes_pre_driver_current_lane0_xe22=0x1
+serdes_pre_driver_current_lane1_xe22=0x1
+serdes_pre_driver_current_lane2_xe22=0x1
+serdes_pre_driver_current_lane3_xe22=0x1
+serdes_preemphasis_lane0_xe22=0xbb10
+serdes_preemphasis_lane1_xe22=0xbb10
+serdes_preemphasis_lane2_xe22=0xbb10
+serdes_preemphasis_lane3_xe22=0xc2f0
+
+# xe23 (40G)
+portmap_24=117:40
+xgxs_rx_lane_map_24=0x231
+xgxs_tx_lane_map_24=0x1203
+phy_xaui_rx_polarity_flip_24=0x3
+phy_xaui_tx_polarity_flip_24=0xe
+serdes_driver_current_lane0_xe23=0x3
+serdes_driver_current_lane1_xe23=0x5
+serdes_driver_current_lane2_xe23=0x3
+serdes_driver_current_lane3_xe23=0x3
+serdes_pre_driver_current_lane0_xe23=0x3
+serdes_pre_driver_current_lane1_xe23=0x5
+serdes_pre_driver_current_lane2_xe23=0x3
+serdes_pre_driver_current_lane3_xe23=0x3
+serdes_preemphasis_lane0_xe23=0xc6e0
+serdes_preemphasis_lane1_xe23=0xc6e0
+serdes_preemphasis_lane2_xe23=0xc6e0
+serdes_preemphasis_lane3_xe23=0xc6e0
+
+# xe24 (40G)
+portmap_25=125:40
+xgxs_rx_lane_map_25=0x132
+xgxs_tx_lane_map_25=0x132
+phy_xaui_rx_polarity_flip_25=0x8
+phy_xaui_tx_polarity_flip_25=0x0
+serdes_driver_current_lane0_xe24=0x4
+serdes_driver_current_lane1_xe24=0x4
+serdes_driver_current_lane2_xe24=0x4
+serdes_driver_current_lane3_xe24=0x4
+serdes_pre_driver_current_lane0_xe24=0x4
+serdes_pre_driver_current_lane1_xe24=0x4
+serdes_pre_driver_current_lane2_xe24=0x4
+serdes_pre_driver_current_lane3_xe24=0x4
+serdes_preemphasis_lane0_xe24=0xc6e0
+serdes_preemphasis_lane1_xe24=0xc6e0
+serdes_preemphasis_lane2_xe24=0xc6e0
+serdes_preemphasis_lane3_xe24=0xcec0
+
+# xe25 (40G)
+portmap_26=121:40
+xgxs_rx_lane_map_26=0x1320
+xgxs_tx_lane_map_26=0x3021
+phy_xaui_rx_polarity_flip_26=0xd
+phy_xaui_tx_polarity_flip_26=0xb
+serdes_driver_current_lane0_xe25=0x4
+serdes_driver_current_lane1_xe25=0x4
+serdes_driver_current_lane2_xe25=0x4
+serdes_driver_current_lane3_xe25=0x4
+serdes_pre_driver_current_lane0_xe25=0x4
+serdes_pre_driver_current_lane1_xe25=0x4
+serdes_pre_driver_current_lane2_xe25=0x4
+serdes_pre_driver_current_lane3_xe25=0x4
+serdes_preemphasis_lane0_xe25=0xc6e0
+serdes_preemphasis_lane1_xe25=0xc6e0
+serdes_preemphasis_lane2_xe25=0xc6e0
+serdes_preemphasis_lane3_xe25=0xc6e0
+
+# xe26 (40G)
+portmap_27=81:40
+xgxs_rx_lane_map_27=0x1320
+xgxs_tx_lane_map_27=0x2031
+phy_xaui_rx_polarity_flip_27=0x1
+phy_xaui_tx_polarity_flip_27=0x2
+serdes_driver_current_lane0_xe26=0x2
+serdes_driver_current_lane1_xe26=0x2
+serdes_driver_current_lane2_xe26=0x2
+serdes_driver_current_lane3_xe26=0x2
+serdes_pre_driver_current_lane0_xe26=0x2
+serdes_pre_driver_current_lane1_xe26=0x2
+serdes_pre_driver_current_lane2_xe26=0x2
+serdes_pre_driver_current_lane3_xe26=0x2
+serdes_preemphasis_lane0_xe26=0xbb10
+serdes_preemphasis_lane1_xe26=0xbb10
+serdes_preemphasis_lane2_xe26=0xbf00
+serdes_preemphasis_lane3_xe26=0xbb10
+
+# xe27 (40G)
+portmap_28=85:40
+xgxs_rx_lane_map_28=0x213
+xgxs_tx_lane_map_28=0x1203
+phy_xaui_rx_polarity_flip_28=0xc
+phy_xaui_tx_polarity_flip_28=0xe
+serdes_driver_current_lane0_xe27=0x4
+serdes_driver_current_lane1_xe27=0x5
+serdes_driver_current_lane2_xe27=0x4
+serdes_driver_current_lane3_xe27=0x5
+serdes_pre_driver_current_lane0_xe27=0x4
+serdes_pre_driver_current_lane1_xe27=0x5
+serdes_pre_driver_current_lane2_xe27=0x4
+serdes_pre_driver_current_lane3_xe27=0x5
+serdes_preemphasis_lane0_xe27=0xc2f0
+serdes_preemphasis_lane1_xe27=0xc6e0
+serdes_preemphasis_lane2_xe27=0xc6e0
+serdes_preemphasis_lane3_xe27=0xc6e0
+
+# xe28 (40G)
+portmap_29=93:40
+xgxs_rx_lane_map_29=0x1320
+xgxs_tx_lane_map_29=0x2031
+phy_xaui_rx_polarity_flip_29=0x1
+phy_xaui_tx_polarity_flip_29=0x2
+serdes_driver_current_lane0_xe28=0x4
+serdes_driver_current_lane1_xe28=0x4
+serdes_driver_current_lane2_xe28=0x4
+serdes_driver_current_lane3_xe28=0x4
+serdes_pre_driver_current_lane0_xe28=0x4
+serdes_pre_driver_current_lane1_xe28=0x4
+serdes_pre_driver_current_lane2_xe28=0x4
+serdes_pre_driver_current_lane3_xe28=0x4
+serdes_preemphasis_lane0_xe28=0xc2f0
+serdes_preemphasis_lane1_xe28=0xc2f0
+serdes_preemphasis_lane2_xe28=0xc2f0
+serdes_preemphasis_lane3_xe28=0xc2f0
+
+# xe29 (40G)
+portmap_30=89:40
+xgxs_rx_lane_map_30=0x1320
+xgxs_tx_lane_map_30=0x3021
+phy_xaui_rx_polarity_flip_30=0x2
+phy_xaui_tx_polarity_flip_30=0xb
+serdes_driver_current_lane0_xe29=0x4
+serdes_driver_current_lane1_xe29=0x4
+serdes_driver_current_lane2_xe29=0x4
+serdes_driver_current_lane3_xe29=0x4
+serdes_pre_driver_current_lane0_xe29=0x4
+serdes_pre_driver_current_lane1_xe29=0x4
+serdes_pre_driver_current_lane2_xe29=0x4
+serdes_pre_driver_current_lane3_xe29=0x4
+serdes_preemphasis_lane0_xe29=0xcad0
+serdes_preemphasis_lane1_xe29=0xc6e0
+serdes_preemphasis_lane2_xe29=0xc6e0
+serdes_preemphasis_lane3_xe29=0xc6e0
+
+# xe30 (40G)
+portmap_31=101:40
+xgxs_rx_lane_map_31=0x1320
+xgxs_tx_lane_map_31=0x1203
+phy_xaui_rx_polarity_flip_31=0x1
+phy_xaui_tx_polarity_flip_31=0x6
+serdes_driver_current_lane0_xe30=0x6
+serdes_driver_current_lane1_xe30=0x6
+serdes_driver_current_lane2_xe30=0x6
+serdes_driver_current_lane3_xe30=0x7
+serdes_pre_driver_current_lane0_xe30=0x6
+serdes_pre_driver_current_lane1_xe30=0x6
+serdes_pre_driver_current_lane2_xe30=0x6
+serdes_pre_driver_current_lane3_xe30=0x7
+serdes_preemphasis_lane0_xe30=0xcec0
+serdes_preemphasis_lane1_xe30=0xcec0
+serdes_preemphasis_lane2_xe30=0xcad0
+serdes_preemphasis_lane3_xe30=0xc6e0
+
+# xe31 (40G)
+portmap_32=97:40
+xgxs_rx_lane_map_32=0x213
+xgxs_tx_lane_map_32=0x2031
+phy_xaui_rx_polarity_flip_32=0xc
+phy_xaui_tx_polarity_flip_32=0x3
+serdes_driver_current_lane0_xe31=0x5
+serdes_driver_current_lane1_xe31=0x5
+serdes_driver_current_lane2_xe31=0x5
+serdes_driver_current_lane3_xe31=0x5
+serdes_pre_driver_current_lane0_xe31=0x5
+serdes_pre_driver_current_lane1_xe31=0x5
+serdes_pre_driver_current_lane2_xe31=0x5
+serdes_pre_driver_current_lane3_xe31=0x5
+serdes_preemphasis_lane0_xe31=0xcad0
+serdes_preemphasis_lane1_xe31=0xcad0
+serdes_preemphasis_lane2_xe31=0xcad0
+serdes_preemphasis_lane3_xe31=0xcad0
diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/topology.sh b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/topology.sh
new file mode 100755
index 000000000000..cf70f3063189
--- /dev/null
+++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/topology.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+#topolgy script for 6 ASIC PLATFORM
+FIRST_FRONTEND_ASIC=0
+LAST_FRONTEND_ASIC=3
+FIRST_BACKEND_ASIC=4
+LAST_BACKEND_ASIC=5
+NUM_INTERFACES_PER_ASIC=32
+
+start () {
+ # Move external links into assigned frontend namespaces
+ # eth0 - eth15: asic2
+ # eth16 - eth31: asic3
+ # eth32 - eth47: asic4
+ # eth48 - eth63: asic5
+ for ASIC in `seq $FIRST_FRONTEND_ASIC $LAST_FRONTEND_ASIC`; do
+ for NUM in `seq 1 16`; do
+ ORIG="eth$((16 * $ASIC + $NUM))"
+ TEMP="ethTemp999"
+ NEW="eth$(($NUM))"
+ echo "$ASIC : $NEW old $ORIG"
+ ip link set dev $ORIG down
+ ip link set dev $ORIG name $TEMP # rename to prevent conflicts before renaming in new namespace
+ ip link set dev $TEMP netns asic$ASIC
+ sudo ip netns exec asic$ASIC ip link set $TEMP name $NEW # rename to final interface name
+ sudo ip netns exec asic$ASIC ip link set $NEW up
+ done
+ done
+
+ # Connect all backend namespaces to frontend namespaces
+ for BACKEND in `seq $FIRST_BACKEND_ASIC $LAST_BACKEND_ASIC`; do
+ for FRONTEND in `seq $FIRST_FRONTEND_ASIC $LAST_FRONTEND_ASIC`; do
+ for LINK in `seq 1 8`; do
+ FRONT_NAME="eth$((8 * $(($BACKEND - $FIRST_BACKEND_ASIC)) + $LINK + 16))"
+ BACK_NAME="eth$((8 * $FRONTEND + $LINK))"
+ echo "$FRONTEND:$FRONT_NAME - $BACKEND:$BACK_NAME"
+ TEMP_BACK="ethBack999"
+ TEMP_FRONT="ethFront999"
+
+ ip link add $TEMP_BACK type veth peer name $TEMP_FRONT # temporary name to prevent conflicts between interfaces
+ ip link set dev $TEMP_BACK netns asic$BACKEND
+ ip link set dev $TEMP_FRONT netns asic$FRONTEND
+
+ sudo ip netns exec asic$BACKEND ip link set $TEMP_BACK name $BACK_NAME
+ sudo ip netns exec asic$FRONTEND ip link set $TEMP_FRONT name $FRONT_NAME
+
+ sudo ip netns exec asic$BACKEND ip link set $BACK_NAME up
+ sudo ip netns exec asic$FRONTEND ip link set $FRONT_NAME up
+ done
+ done
+ done
+}
+
+stop() {
+ for ASIC in `seq $FIRST_FRONTEND_ASIC $LAST_FRONTEND_ASIC`; do
+ for NUM in `seq 1 16`; do
+ TEMP="eth999"
+ OLD="eth$((16 * $ASIC + $NUM))"
+ NAME="eth$((16 * $ASIC + $NUM - 1))"
+ sudo ip netns exec asic$ASIC ip link set dev $OLD down
+ sudo ip netns exec asic$ASIC ip link set dev $OLD name $TEMP
+ sudo ip netns exec asic$ASIC ip link set dev $TEMP netns 1
+ ip link set dev $TEMP name $NAME
+ ip link set dev $NAME up
+ done
+ done
+
+ for ASIC in `seq $FIRST_BACKEND_ASIC $LAST_BACKEND_ASIC`; do
+ for NUM in `seq 1 $NUM_INTERFACES_PER_ASIC`; do
+ sudo ip netns exec asic$ASIC ip link set dev eth$NUM down
+ sudo ip netns exec asic$ASIC ip link delete dev eth$NUM
+ done
+ done
+}
+
+case "$1" in
+ start|stop)
+ $1
+ ;;
+ *)
+ echo "Usage: $0 {start|stop}"
+ ;;
+esac
diff --git a/dockers/docker-base-stretch/Dockerfile.j2 b/dockers/docker-base-stretch/Dockerfile.j2
index d8188a06afd6..dea58a210f89 100644
--- a/dockers/docker-base-stretch/Dockerfile.j2
+++ b/dockers/docker-base-stretch/Dockerfile.j2
@@ -34,7 +34,7 @@ COPY ["sources.list.arm64", "/etc/apt/sources.list"]
COPY ["sources.list", "/etc/apt/sources.list"]
{% endif %}
COPY ["no_install_recommend_suggest", "/etc/apt/apt.conf.d"]
-COPY ["aptconf_archive_expired_release", "/etc/apt/apt.conf.d"]
+COPY ["no-check-valid-until", "/etc/apt/apt.conf.d"]
# Update apt cache and
# pre-install fundamental packages
diff --git a/dockers/docker-base-stretch/aptconf_archive_expired_release b/dockers/docker-base-stretch/aptconf_archive_expired_release
deleted file mode 100644
index 67bc409b2174..000000000000
--- a/dockers/docker-base-stretch/aptconf_archive_expired_release
+++ /dev/null
@@ -1,3 +0,0 @@
-# Instruct apt-get to override expired releases repo list for jessie archives
-
-Acquire::Check-Valid-Until "0";
diff --git a/dockers/docker-base-stretch/dpkg_01_drop b/dockers/docker-base-stretch/dpkg_01_drop
index e75ef3147158..d749943797d9 100644
--- a/dockers/docker-base-stretch/dpkg_01_drop
+++ b/dockers/docker-base-stretch/dpkg_01_drop
@@ -20,3 +20,11 @@ path-exclude /usr/share/pyshared/twisted/test*
path-exclude /usr/lib/python*/dist-packages/twisted/test*
path-exclude /usr/share/pyshared/twisted/*/test*
path-exclude /usr/lib/python*/dist-packages/twisted/*/test*
+
+## install the configuration file if it’s currently missing
+force-confmiss
+## combined with confold: overwrite configuration files that you have not modified
+force-confdef
+## do not modify the current configuration file, the new version is installed with a .dpkg-dist suffix
+force-confold
+
diff --git a/dockers/docker-base-stretch/no-check-valid-until b/dockers/docker-base-stretch/no-check-valid-until
new file mode 100644
index 000000000000..c7c25d017f7f
--- /dev/null
+++ b/dockers/docker-base-stretch/no-check-valid-until
@@ -0,0 +1,4 @@
+# Instruct apt-get to NOT check the "Valid Until" date in Release files
+# Once the Debian team archives a repo, they stop updating this date
+
+Acquire::Check-Valid-Until "false";
diff --git a/dockers/docker-base/Dockerfile.j2 b/dockers/docker-base/Dockerfile.j2
index cb2ff80186a3..e45235a1e139 100644
--- a/dockers/docker-base/Dockerfile.j2
+++ b/dockers/docker-base/Dockerfile.j2
@@ -32,7 +32,7 @@ COPY ["dpkg_01_drop", "/etc/dpkg/dpkg.cfg.d/01_drop"]
COPY ["sources.list.armhf", "/etc/apt/sources.list"]
{% elif CONFIGURED_ARCH == "arm64" %}
COPY ["sources.list.arm64", "/etc/apt/sources.list"]
-COPY ["aptconf_archive_expired_release", "/etc/apt/apt.conf.d"]
+COPY ["no-check-valid-until", "/etc/apt/apt.conf.d"]
{% else %}
COPY ["sources.list", "/etc/apt/sources.list"]
{% endif %}
diff --git a/dockers/docker-base/aptconf_archive_expired_release b/dockers/docker-base/aptconf_archive_expired_release
deleted file mode 100644
index 67bc409b2174..000000000000
--- a/dockers/docker-base/aptconf_archive_expired_release
+++ /dev/null
@@ -1,3 +0,0 @@
-# Instruct apt-get to override expired releases repo list for jessie archives
-
-Acquire::Check-Valid-Until "0";
diff --git a/dockers/docker-base/dpkg_01_drop b/dockers/docker-base/dpkg_01_drop
index e75ef3147158..d749943797d9 100644
--- a/dockers/docker-base/dpkg_01_drop
+++ b/dockers/docker-base/dpkg_01_drop
@@ -20,3 +20,11 @@ path-exclude /usr/share/pyshared/twisted/test*
path-exclude /usr/lib/python*/dist-packages/twisted/test*
path-exclude /usr/share/pyshared/twisted/*/test*
path-exclude /usr/lib/python*/dist-packages/twisted/*/test*
+
+## install the configuration file if it’s currently missing
+force-confmiss
+## combined with confold: overwrite configuration files that you have not modified
+force-confdef
+## do not modify the current configuration file, the new version is installed with a .dpkg-dist suffix
+force-confold
+
diff --git a/dockers/docker-base/no-check-valid-until b/dockers/docker-base/no-check-valid-until
new file mode 100644
index 000000000000..c7c25d017f7f
--- /dev/null
+++ b/dockers/docker-base/no-check-valid-until
@@ -0,0 +1,4 @@
+# Instruct apt-get to NOT check the "Valid Until" date in Release files
+# Once the Debian team archives a repo, they stop updating this date
+
+Acquire::Check-Valid-Until "false";
diff --git a/dockers/docker-database/Dockerfile.j2 b/dockers/docker-database/Dockerfile.j2
index acb5e013fb84..8cd181614672 100644
--- a/dockers/docker-database/Dockerfile.j2
+++ b/dockers/docker-database/Dockerfile.j2
@@ -36,5 +36,7 @@ COPY ["supervisord.conf.j2", "/usr/share/sonic/templates/"]
COPY ["docker-database-init.sh", "/usr/local/bin/"]
COPY ["ping_pong_db_insts", "/usr/local/bin/"]
COPY ["database_config.json", "/etc/default/sonic-db/"]
+COPY ["files/supervisor-proc-exit-listener", "/usr/bin"]
+COPY ["critical_processes", "/etc/supervisor"]
ENTRYPOINT ["/usr/local/bin/docker-database-init.sh"]
diff --git a/dockers/docker-database/base_image_files/monit_database b/dockers/docker-database/base_image_files/monit_database
new file mode 100644
index 000000000000..c5508922864e
--- /dev/null
+++ b/dockers/docker-database/base_image_files/monit_database
@@ -0,0 +1,7 @@
+###############################################################################
+## Monit configuration for database container
+## process list:
+## redis_server
+###############################################################################
+check process redis_server matching "/usr/bin/redis-server"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/dockers/docker-database/critical_processes b/dockers/docker-database/critical_processes
new file mode 100644
index 000000000000..7800f0fad3ff
--- /dev/null
+++ b/dockers/docker-database/critical_processes
@@ -0,0 +1 @@
+redis
diff --git a/dockers/docker-database/supervisord.conf.j2 b/dockers/docker-database/supervisord.conf.j2
index 110619f762be..9e855527edba 100644
--- a/dockers/docker-database/supervisord.conf.j2
+++ b/dockers/docker-database/supervisord.conf.j2
@@ -3,6 +3,12 @@ logfile_maxbytes=1MB
logfile_backups=2
nodaemon=true
+[eventlistener:supervisor-proc-exit-listener]
+command=/usr/bin/supervisor-proc-exit-listener --container-name database
+events=PROCESS_STATE_EXITED
+autostart=true
+autorestart=unexpected
+
[program:rsyslogd]
command=/bin/bash -c "rm -f /var/run/rsyslogd.pid && /usr/sbin/rsyslogd -n"
priority=1
diff --git a/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 b/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2
index e738e8699e6c..d52400480775 100644
--- a/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2
+++ b/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name dhcp_relay
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
@@ -85,5 +85,53 @@ stderr_logfile=syslog
{% endif %}
{% endif %}
{% endfor %}
+
+[group:dhcpmon]
+programs=
+{%- set add_preceding_comma = { 'flag': False } %}
+{% for vlan_name in VLAN %}
+{% if VLAN[vlan_name]['dhcp_servers'] %}
+{% if add_preceding_comma.flag %},{% endif %}
+{% set _dummy = add_preceding_comma.update({'flag': True}) %}
+dhcpmon-{{ vlan_name }}
+{%- endif %}
+{% endfor %}
+
+
+{# Create a program entry for each DHCP MONitor instance #}
+{% set relay_for_ipv4 = { 'flag': False } %}
+{% for vlan_name in VLAN %}
+{% if VLAN[vlan_name]['dhcp_servers'] %}
+{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %}
+{% if dhcp_server | ipv4 %}
+{% set _dummy = relay_for_ipv4.update({'flag': True}) %}
+{% endif %}
+{% endfor %}
+{% if relay_for_ipv4.flag %}
+{% set _dummy = relay_for_ipv4.update({'flag': False}) %}
+[program:dhcpmon-{{ vlan_name }}]
+{# We treat this VLAN as a downstream interface (-id), as we only want to listen for requests #}
+command=/usr/sbin/dhcpmon -id {{ vlan_name }}
+{#- We treat all other interfaces as upstream interfaces (-iu), as we only want to listen for replies #}
+{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %}
+{% if prefix | ipv4 and name != vlan_name %} -iu {{ name }}{% endif -%}
+{% endfor %}
+{% for (name, prefix) in INTERFACE|pfx_filter %}
+{% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
+{% endfor %}
+{% for (name, prefix) in PORTCHANNEL_INTERFACE|pfx_filter %}
+{% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
+{% endfor %}
+
+priority=4
+autostart=false
+autorestart=false
+stdout_logfile=syslog
+stderr_logfile=syslog
+
+{% endif %}
+{% endif %}
+{% endfor %}
+
{% endif %}
{% endif %}
diff --git a/dockers/docker-dhcp-relay/start.sh b/dockers/docker-dhcp-relay/start.sh
index 0ac5ea1a10ec..dbbf32251080 100755
--- a/dockers/docker-dhcp-relay/start.sh
+++ b/dockers/docker-dhcp-relay/start.sh
@@ -19,3 +19,9 @@ if [ $(supervisorctl status | grep -c "^isc-dhcp-relay:") -gt 0 ]; then
# Start all DHCP relay agent(s)
supervisorctl start isc-dhcp-relay:*
fi
+
+# If our supervisor config has entries in the "dhcpmon" group...
+if [ $(supervisorctl status | grep -c "^dhcpmon:") -gt 0 ]; then
+ # Start all DHCP Monitor daemon(s)
+ supervisorctl start dhcpmon:*
+fi
diff --git a/dockers/docker-dhcp-relay/wait_for_intf.sh.j2 b/dockers/docker-dhcp-relay/wait_for_intf.sh.j2
index 0488799a4c81..568f128b3772 100644
--- a/dockers/docker-dhcp-relay/wait_for_intf.sh.j2
+++ b/dockers/docker-dhcp-relay/wait_for_intf.sh.j2
@@ -1,7 +1,5 @@
#!/usr/bin/env bash
-STATE_DB_IDX="6"
-
function wait_until_iface_ready
{
IFACE_NAME=$1
@@ -12,7 +10,7 @@ function wait_until_iface_ready
# Wait for the interface to come up
# (i.e., interface is present in STATE_DB and state is "ok")
while true; do
- RESULT=$(redis-cli -n ${STATE_DB_IDX} HGET "INTERFACE_TABLE|${IFACE_NAME}|${IFACE_CIDR}" "state" 2> /dev/null)
+ RESULT=$(sonic-db-cli STATE_DB HGET "INTERFACE_TABLE|${IFACE_NAME}|${IFACE_CIDR}" "state" 2> /dev/null)
if [ x"$RESULT" == x"ok" ]; then
break
fi
diff --git a/dockers/docker-fpm-frr/Dockerfile.j2 b/dockers/docker-fpm-frr/Dockerfile.j2
index 418676c18329..1c670682a342 100644
--- a/dockers/docker-fpm-frr/Dockerfile.j2
+++ b/dockers/docker-fpm-frr/Dockerfile.j2
@@ -50,6 +50,8 @@ COPY ["snmp.conf", "/etc/snmp/frr.conf"]
COPY ["TSA", "/usr/bin/TSA"]
COPY ["TSB", "/usr/bin/TSB"]
COPY ["TSC", "/usr/bin/TSC"]
+COPY ["files/supervisor-proc-exit-listener", "/usr/bin"]
+COPY ["critical_processes", "/etc/supervisor"]
RUN chmod a+x /usr/bin/TSA && \
chmod a+x /usr/bin/TSB && \
chmod a+x /usr/bin/TSC
diff --git a/dockers/docker-fpm-frr/base_image_files/monit_bgp b/dockers/docker-fpm-frr/base_image_files/monit_bgp
new file mode 100644
index 000000000000..5b943ea7c0bb
--- /dev/null
+++ b/dockers/docker-fpm-frr/base_image_files/monit_bgp
@@ -0,0 +1,23 @@
+###############################################################################
+## Monit configuration for BGP container
+## process list:
+## zebra
+## fpmsyncd
+## bgpd
+## staticd
+## bgpcfgd
+###############################################################################
+check process zebra matching "/usr/lib/frr/zebra"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process fpmsyncd matching "fpmsyncd"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process bgpd matching "/usr/lib/frr/bgpd"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process staticd matching "/usr/lib/frr/staticd"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process bgpcfgd matching "python /usr/bin/bgpcfgd"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/dockers/docker-fpm-frr/bgpcfgd b/dockers/docker-fpm-frr/bgpcfgd
index 4211f49d2272..4e638def47b7 100755
--- a/dockers/docker-fpm-frr/bgpcfgd
+++ b/dockers/docker-fpm-frr/bgpcfgd
@@ -86,9 +86,10 @@ class Daemon(object):
self.callbacks = defaultdict(lambda : defaultdict(list)) # db -> table -> []
self.subscribers = set()
- def add_manager(self, db, table_name, callback):
+ def add_manager(self, db_name, table_name, callback):
+ db = swsscommon.SonicDBConfig.getDbId(db_name)
if db not in self.db_connectors:
- self.db_connectors[db] = swsscommon.DBConnector(db, swsscommon.DBConnector.DEFAULT_UNIXSOCKET, 0)
+ self.db_connectors[db] = swsscommon.DBConnector(db_name, 0)
if table_name not in self.callbacks[db]:
conn = self.db_connectors[db]
@@ -203,6 +204,8 @@ class Manager(object):
syslog.syslog(syslog.LOG_ERR, 'Invalid operation "%s" for key "%s"' % (op, key))
def on_deps_change(self):
+ if not self.directory.available_deps(self.deps):
+ return
new_queue = []
for key, data in self.set_queue:
res = self.set_handler(key, data)
@@ -223,7 +226,7 @@ class BGPDeviceMetaMgr(Manager):
daemon,
directory,
[],
- swsscommon.CONFIG_DB,
+ "CONFIG_DB",
swsscommon.CFG_DEVICE_METADATA_TABLE_NAME
)
@@ -248,7 +251,7 @@ class BGPNeighborMetaMgr(Manager):
daemon,
directory,
[],
- swsscommon.CONFIG_DB,
+ "CONFIG_DB",
swsscommon.CFG_DEVICE_NEIGHBOR_METADATA_TABLE_NAME
)
@@ -269,8 +272,10 @@ class BGPPeerMgr(Manager):
[
("meta", "localhost/bgp_asn"),
("neigmeta", ""),
+ ("local_addresses", ""),
+ ("interfaces", ""),
],
- swsscommon.CONFIG_DB,
+ "CONFIG_DB",
swsscommon.CFG_BGP_NEIGHBOR_TABLE_NAME
)
self.peers = self.load_peers()
@@ -287,8 +292,42 @@ class BGPPeerMgr(Manager):
vrf, nbr = key.split('|', 1)
if key not in self.peers:
cmd = None
+
+ if "local_addr" not in data:
+ syslog.syslog(syslog.LOG_WARNING, 'Peer {}. Error in missing required attribute "local_addr"'.format(key))
+ else:
+ # The bgp session that belongs to a vnet cannot be advertised as the default BGP session.
+ # So we need to check whether this bgp session belongs to a vnet.
+ interface = InterfaceMgr.get_local_interface(self.directory, data["local_addr"])
+ if not interface:
+ syslog.syslog(syslog.LOG_INFO,
+ 'Peer {} with local address {} wait for the corresponding interface to be set'.format(
+ key,
+ data["local_addr"]
+ )
+ )
+ return False
+ vnet = InterfaceMgr.get_vnet(interface)
+ if vnet:
+ # Ignore the bgp session that is in a vnet
+ syslog.syslog(
+ syslog.LOG_INFO,
+ 'Ignore the BGP peer {} as the interface {} is in vnet {}'.format(
+ key,
+ interface,
+ vnet
+ )
+ )
+ return True
+
neigmeta = self.directory.get_slot("neigmeta")
if 'name' in data and data["name"] not in neigmeta:
+ syslog.syslog(syslog.LOG_INFO,
+ 'Peer {} with neighbor name {} wait for the corresponding neighbor metadata to be set'.format(
+ key,
+ data["name"]
+ )
+ )
return False
try:
cmd = self.templates["add"].render(
@@ -387,6 +426,121 @@ class BGPPeerMgr(Manager):
return peers
+class InterfaceMgr(Manager):
+ def __init__(self, daemon, directory, interface_table = swsscommon.CFG_INTF_TABLE_NAME):
+ super(InterfaceMgr, self).__init__(
+ daemon,
+ directory,
+ [],
+ "CONFIG_DB",
+ interface_table
+ )
+
+ def set_handler(self, key, data):
+ # Interface table can have two keys,
+ # one with ip prefix and one without ip prefix
+ if '|' in key:
+ data = {}
+ data["interface"], network = key.split('|', 1)
+ try:
+ network = netaddr.IPNetwork(str(network))
+ except:
+ syslog.syslog(
+ syslog.LOG_WARNING,
+ 'Subnet {} format is wrong for interface {}'.format(
+ network,
+ data["interface"]
+ )
+ )
+ return False
+ data["prefixlen"] = str(network.prefixlen)
+ ip = str(network.ip)
+ self.directory.put("local_addresses", ip, data)
+ else:
+ self.directory.put("interfaces", key, data)
+ return True
+
+ def del_handler(self, key):
+ if '|' in key:
+ interface, network = key.split('|', 1)
+ try:
+ network = netaddr.IPNetwork(str(network))
+ except:
+ syslog.syslog(
+ syslog.LOG_WARNING,
+ 'Subnet {} format is wrong for interface {}'.format(
+ network,
+ interface
+ )
+ )
+ return False
+ ip = str(network.ip)
+ self.directory.remove("local_addresses", ip)
+ else:
+ self.directory.remove("interfaces", key)
+
+ @staticmethod
+ def get_local_interface(directory, local_addr):
+ """
+ @summary: Get interface according to the local address from the directory
+ @param directory: Directory object that stored metadata of interfaces
+ @param local_addr: Local address of the interface
+ @return: Return the metadata of the interface with the local address
+ If the interface has not been set, return None
+ """
+ local_addresses = directory.get_slot("local_addresses")
+ # Check if the local address of this bgp session has been set
+ if local_addr not in local_addresses:
+ return None
+ local_address = local_addresses[local_addr]
+ interfaces = directory.get_slot("interfaces")
+ # Check if the information for the interface of this local address has been set
+ if local_address.has_key("interface") and local_address["interface"] in interfaces:
+ return interfaces[local_address["interface"]]
+ else:
+ return None
+
+ @staticmethod
+ def get_vnet(interface):
+ """
+ @summary: Get the VNet name of the interface
+ @param interface: The metadata of the interface
+ @return: Return the vnet name of the interface if this interface belongs to a vnet,
+ Otherwise return None
+ """
+ if interface.has_key("vnet_name") and interface["vnet_name"]:
+ return interface["vnet_name"]
+ else:
+ return None
+
+
+class LoopbackInterfaceMgr(InterfaceMgr):
+ def __init__(self, daemon, directory):
+ super(LoopbackInterfaceMgr, self).__init__(
+ daemon,
+ directory,
+ swsscommon.CFG_LOOPBACK_INTERFACE_TABLE_NAME
+ )
+
+
+class VlanInterfaceMgr(InterfaceMgr):
+ def __init__(self, daemon, directory):
+ super(VlanInterfaceMgr, self).__init__(
+ daemon,
+ directory,
+ swsscommon.CFG_VLAN_INTF_TABLE_NAME
+ )
+
+
+class PortChannelInterfaceMgr(InterfaceMgr):
+ def __init__(self, daemon, directory):
+ super(PortChannelInterfaceMgr, self).__init__(
+ daemon,
+ directory,
+ swsscommon.CFG_LAG_INTF_TABLE_NAME
+ )
+
+
def wait_for_bgpd():
# wait for 20 seconds
stop_time = datetime.datetime.now() + datetime.timedelta(seconds=20)
@@ -405,6 +559,10 @@ def main():
BGPDeviceMetaMgr,
BGPNeighborMetaMgr,
BGPPeerMgr,
+ InterfaceMgr,
+ LoopbackInterfaceMgr,
+ VlanInterfaceMgr,
+ PortChannelInterfaceMgr,
]
wait_for_bgpd()
daemon = Daemon()
diff --git a/dockers/docker-fpm-frr/bgpd.conf.default.j2 b/dockers/docker-fpm-frr/bgpd.conf.default.j2
index e12782b035aa..2bf80b80a787 100644
--- a/dockers/docker-fpm-frr/bgpd.conf.default.j2
+++ b/dockers/docker-fpm-frr/bgpd.conf.default.j2
@@ -23,6 +23,20 @@ route-map TO_BGP_PEER_V4 permit 100
!
route-map TO_BGP_PEER_V6 permit 100
!
+{% if DEVICE_METADATA['localhost']['type'] == 'InternalFrontend' %}
+route-map HIDE_INTERNAL permit 10
+ set community local-AS
+!
+{% endif %}
+{% if DEVICE_METADATA['localhost']['type'] == 'InternalBackend' %}
+route-map OVERRIDE_ORIGINATOR_ID permit 10
+{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %}
+{% if prefix | ipv4 and name == 'Loopback0' %}
+ set originator-id {{ prefix | ip }}
+{% endif %}
+{% endfor %}
+!
+{% endif %}
{% if BGP_MONITORS is defined and BGP_MONITORS|length > 0 %}
route-map FROM_BGPMON deny 10
!
@@ -37,6 +51,9 @@ route-map set-next-hop-global-v6 permit 10
set ipv6 next-hop prefer-global
!
router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
+{% if DEVICE_METADATA['localhost']['type'] == 'InternalFrontend' %}
+ redistribute connected route-map HIDE_INTERNAL
+{% endif %}
bgp log-neighbor-changes
bgp bestpath as-path multipath-relax
no bgp default ipv4-unicast
@@ -151,6 +168,9 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
neighbor {{ neighbor_addr }} peer-group BGPMON
neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }}
neighbor {{ neighbor_addr }} activate
+{% if DEVICE_METADATA['localhost']['type'] == 'InternalBackend' %}
+ neighbor {{ neighbor_addr }} route-map OVERRIDE_ORIGINATOR_ID in
+{% endif %}
address-family ipv6
neighbor {{ neighbor_addr }} activate
exit-address-family
diff --git a/dockers/docker-fpm-frr/bgpd.peer.conf.j2 b/dockers/docker-fpm-frr/bgpd.peer.conf.j2
old mode 100644
new mode 100755
index c3dc50449d35..bcc520f6b2df
--- a/dockers/docker-fpm-frr/bgpd.peer.conf.j2
+++ b/dockers/docker-fpm-frr/bgpd.peer.conf.j2
@@ -26,8 +26,7 @@
neighbor {{ neighbor_addr }} next-hop-self
{% endif %}
{% if bgp_session["asn"] == DEVICE_METADATA['localhost']['bgp_asn']
- and DEVICE_METADATA['localhost']['type'] == "SpineChassisFrontendRouter"
- and (not bgp_session.has_key("local_addr") or bgp_session["local_addr"] not in interfaces_in_vnets) %}
+ and DEVICE_METADATA['localhost']['type'] == "SpineChassisFrontendRouter" %}
address-family l2vpn evpn
neighbor {{ neighbor_addr }} activate
advertise-all-vni
diff --git a/dockers/docker-fpm-frr/critical_processes b/dockers/docker-fpm-frr/critical_processes
new file mode 100644
index 000000000000..8ea09e1bb538
--- /dev/null
+++ b/dockers/docker-fpm-frr/critical_processes
@@ -0,0 +1,5 @@
+zebra
+staticd
+bgpd
+fpmsyncd
+bgpcfgd
diff --git a/dockers/docker-fpm-frr/supervisord.conf b/dockers/docker-fpm-frr/supervisord.conf
index fe0ce6eda1a4..3e544b64b296 100644
--- a/dockers/docker-fpm-frr/supervisord.conf
+++ b/dockers/docker-fpm-frr/supervisord.conf
@@ -3,6 +3,12 @@ logfile_maxbytes=1MB
logfile_backups=2
nodaemon=true
+[eventlistener:supervisor-proc-exit-listener]
+command=/usr/bin/supervisor-proc-exit-listener --container-name bgp
+events=PROCESS_STATE_EXITED
+autostart=true
+autorestart=unexpected
+
[program:start.sh]
command=/usr/bin/start.sh
priority=1
@@ -25,7 +31,7 @@ stderr_logfile=syslog
command=/usr/sbin/rsyslogd -n
priority=3
autostart=false
-autorestart=false
+autorestart=unexpected
startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
diff --git a/dockers/docker-fpm-gobgp/Dockerfile.j2 b/dockers/docker-fpm-gobgp/Dockerfile.j2
index 1e333d9026c0..b9b969edeb09 100644
--- a/dockers/docker-fpm-gobgp/Dockerfile.j2
+++ b/dockers/docker-fpm-gobgp/Dockerfile.j2
@@ -24,5 +24,7 @@ COPY ["start.sh", "/usr/bin/"]
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
COPY ["*.j2", "/usr/share/sonic/templates/"]
COPY ["daemons", "/etc/quagga/"]
+COPY ["files/supervisor-proc-exit-listener", "/usr/bin"]
+COPY ["critical_processes", "/etc/supervisor"]
ENTRYPOINT ["/usr/bin/supervisord"]
diff --git a/dockers/docker-fpm-gobgp/critical_processes b/dockers/docker-fpm-gobgp/critical_processes
new file mode 100644
index 000000000000..2a9e47831e0d
--- /dev/null
+++ b/dockers/docker-fpm-gobgp/critical_processes
@@ -0,0 +1,2 @@
+gobgpd
+fpmsyncd
diff --git a/dockers/docker-fpm-gobgp/supervisord.conf b/dockers/docker-fpm-gobgp/supervisord.conf
index 4e635f4093d4..b814dc024fa3 100644
--- a/dockers/docker-fpm-gobgp/supervisord.conf
+++ b/dockers/docker-fpm-gobgp/supervisord.conf
@@ -3,6 +3,12 @@ logfile_maxbytes=1MB
logfile_backups=2
nodaemon=true
+[eventlistener:supervisor-proc-exit-listener]
+command=/usr/bin/supervisor-proc-exit-listener --container-name bgp
+events=PROCESS_STATE_EXITED
+autostart=true
+autorestart=unexpected
+
[program:start.sh]
command=/usr/bin/start.sh
priority=1
@@ -15,7 +21,7 @@ stderr_logfile=syslog
command=/usr/sbin/rsyslogd -n
priority=2
autostart=false
-autorestart=false
+autorestart=unexpected
stdout_logfile=syslog
stderr_logfile=syslog
diff --git a/dockers/docker-fpm-quagga/Dockerfile.j2 b/dockers/docker-fpm-quagga/Dockerfile.j2
index f048e2789429..9d1312d073ee 100644
--- a/dockers/docker-fpm-quagga/Dockerfile.j2
+++ b/dockers/docker-fpm-quagga/Dockerfile.j2
@@ -33,5 +33,7 @@ RUN rm -rf /debs ~/.cache
COPY ["bgpcfgd", "start.sh", "/usr/bin/"]
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
COPY ["*.j2", "/usr/share/sonic/templates/"]
+COPY ["files/supervisor-proc-exit-listener", "/usr/bin"]
+COPY ["critical_processes", "/etc/supervisor"]
ENTRYPOINT ["/usr/bin/supervisord"]
diff --git a/dockers/docker-fpm-quagga/critical_processes b/dockers/docker-fpm-quagga/critical_processes
new file mode 100644
index 000000000000..f151af9c4bdd
--- /dev/null
+++ b/dockers/docker-fpm-quagga/critical_processes
@@ -0,0 +1,4 @@
+zebra
+bgpd
+fpmsyncd
+bgpcfgd
diff --git a/dockers/docker-fpm-quagga/supervisord.conf b/dockers/docker-fpm-quagga/supervisord.conf
index c4351fafefe9..7397a7428a08 100644
--- a/dockers/docker-fpm-quagga/supervisord.conf
+++ b/dockers/docker-fpm-quagga/supervisord.conf
@@ -3,6 +3,12 @@ logfile_maxbytes=1MB
logfile_backups=2
nodaemon=true
+[eventlistener:supervisor-proc-exit-listener]
+command=/usr/bin/supervisor-proc-exit-listener --container-name bgp
+events=PROCESS_STATE_EXITED
+autostart=true
+autorestart=unexpected
+
[program:start.sh]
command=/usr/bin/start.sh
priority=1
@@ -25,7 +31,7 @@ stderr_logfile=syslog
command=/usr/sbin/rsyslogd -n
priority=3
autostart=false
-autorestart=false
+autorestart=unexpected
startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
diff --git a/dockers/docker-lldp-sv2/base_image_files/monit_lldp b/dockers/docker-lldp-sv2/base_image_files/monit_lldp
new file mode 100644
index 000000000000..200c52c7d332
--- /dev/null
+++ b/dockers/docker-lldp-sv2/base_image_files/monit_lldp
@@ -0,0 +1,15 @@
+###############################################################################
+## Monit configuration for lldp container
+## process list:
+## lldpd
+## lldp-syncd
+## lldpmgrd
+###############################################################################
+check process lldpd_monitor matching "lldpd: "
+ if does not exist for 5 times within 5 cycles then alert
+
+check process lldp_syncd matching "python2 -m lldp_syncd"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process lldpmgrd matching "python /usr/bin/lldpmgrd"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/dockers/docker-lldp-sv2/lldpmgrd b/dockers/docker-lldp-sv2/lldpmgrd
index edcdc5c42e47..7e9ef1642a06 100755
--- a/dockers/docker-lldp-sv2/lldpmgrd
+++ b/dockers/docker-lldp-sv2/lldpmgrd
@@ -84,22 +84,18 @@ class LldpManager(object):
pending_cmds: Dictionary where key is port name, value is pending
LLDP configuration command to run
"""
- REDIS_HOSTNAME = "localhost"
- REDIS_PORT = 6379
REDIS_TIMEOUT_MS = 0
def __init__(self):
# Open a handle to the Config database
- self.config_db = swsscommon.DBConnector(swsscommon.CONFIG_DB,
- self.REDIS_HOSTNAME,
- self.REDIS_PORT,
- self.REDIS_TIMEOUT_MS)
+ self.config_db = swsscommon.DBConnector("CONFIG_DB",
+ self.REDIS_TIMEOUT_MS,
+ True)
# Open a handle to the Application database
- self.appl_db = swsscommon.DBConnector(swsscommon.APPL_DB,
- self.REDIS_HOSTNAME,
- self.REDIS_PORT,
- self.REDIS_TIMEOUT_MS)
+ self.appl_db = swsscommon.DBConnector("APPL_DB",
+ self.REDIS_TIMEOUT_MS,
+ True)
self.pending_cmds = {}
@@ -157,7 +153,7 @@ class LldpManager(object):
# if there is a description available, also configure that
if port_desc:
- lldpcli_cmd += " description {}".format(port_desc)
+ lldpcli_cmd += " description '{}'".format(port_desc)
else:
log_info("Unable to retrieve description for port '{}'. Not adding port description".format(port_name))
diff --git a/dockers/docker-lldp-sv2/supervisord.conf b/dockers/docker-lldp-sv2/supervisord.conf
index 3f3f5beabc8d..73ff52f4420e 100644
--- a/dockers/docker-lldp-sv2/supervisord.conf
+++ b/dockers/docker-lldp-sv2/supervisord.conf
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name lldp
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
diff --git a/dockers/docker-nat/Dockerfile.j2 b/dockers/docker-nat/Dockerfile.j2
new file mode 100644
index 000000000000..a74147cc26fd
--- /dev/null
+++ b/dockers/docker-nat/Dockerfile.j2
@@ -0,0 +1,48 @@
+{% from "dockers/dockerfile-macros.j2" import install_debian_packages, copy_files %}
+FROM docker-config-engine-stretch
+
+ARG docker_container_name
+RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf
+
+RUN echo
+
+## Make apt-get non-interactive
+ENV DEBIAN_FRONTEND=noninteractive
+
+## Install redis-tools dependencies
+## TODO: implicitly install dependencies
+RUN apt-get update \
+&& apt-get install -f -y \
+ libdbus-1-3 \
+ libdaemon0 \
+ libjansson4 \
+ libpython2.7 \
+ libatomic1 \
+ libjemalloc1 \
+ liblua5.1-0 \
+ lua-bitop \
+ lua-cjson \
+ libelf1 \
+ libmnl0 \
+ bridge-utils \
+ conntrack
+
+{% if docker_nat_debs.strip() -%}
+# Copy locally-built Debian package dependencies
+{{copy_files ("debs/", docker_nat_debs.split(' '), "/debs/") }}
+
+# Install locally-built Debian packages and implicitly install their dependencies
+{{ install_debian_packages(docker_nat_debs.split(' ')) }}
+{%- endif %}
+
+COPY ["start.sh", "/usr/bin/"]
+COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
+COPY ["restore_nat_entries.py", "/usr/bin/"]
+COPY ["files/supervisor-proc-exit-listener", "/usr/bin"]
+COPY ["critical_processes", "/etc/supervisor"]
+
+RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y
+RUN rm -rf /debs
+
+ENTRYPOINT ["/usr/bin/supervisord"]
+
diff --git a/dockers/docker-nat/base_image_files/natctl b/dockers/docker-nat/base_image_files/natctl
new file mode 100644
index 000000000000..6cba3c86be70
--- /dev/null
+++ b/dockers/docker-nat/base_image_files/natctl
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+# -t option needed only for shell, not for commands
+
+docker exec -i nat natctl "$@"
diff --git a/dockers/docker-nat/critical_processes b/dockers/docker-nat/critical_processes
new file mode 100644
index 000000000000..d442976143f1
--- /dev/null
+++ b/dockers/docker-nat/critical_processes
@@ -0,0 +1,2 @@
+natmgrd
+natsyncd
diff --git a/dockers/docker-nat/restore_nat_entries.py b/dockers/docker-nat/restore_nat_entries.py
new file mode 100755
index 000000000000..9fb62e82f573
--- /dev/null
+++ b/dockers/docker-nat/restore_nat_entries.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+
+""""
+Description: restore_nat_entries.py -- restoring nat entries table into kernel during system warm reboot.
+ The script is started by supervisord in nat docker when the docker is started.
+ It does not do anything in case neither system nor nat warm restart is enabled.
+ In case nat warm restart enabled only, it sets the stateDB flag so natsyncd can continue
+ the reconciation process.
+ In case system warm reboot is enabled, it will try to restore the nat entries table into kernel
+ , then it sets the stateDB flag for natsyncd to continue the
+ reconciliation process.
+"""
+
+import sys
+import subprocess
+from swsscommon import swsscommon
+import logging
+import logging.handlers
+import re
+import os
+
+WARM_BOOT_FILE_DIR = '/var/warmboot/nat/'
+NAT_WARM_BOOT_FILE = 'nat_entries.dump'
+IP_PROTO_TCP = '6'
+
+MATCH_CONNTRACK_ENTRY = '^(\w+)\s+(\d+).*src=([\d.]+)\s+dst=([\d.]+)\s+sport=(\d+)\s+dport=(\d+).*src=([\d.]+)\s+dst=([\d.]+)\s+sport=(\d+)\s+dport=(\d+)'
+REDIS_SOCK = "/var/run/redis/redis.sock"
+
+logger = logging.getLogger(__name__)
+logger.setLevel(logging.INFO)
+handler = logging.handlers.SysLogHandler(address = '/dev/log')
+logger.addHandler(handler)
+
+def add_nat_conntrack_entry_in_kernel(ipproto, srcip, dstip, srcport, dstport, natsrcip, natdstip, natsrcport, natdstport):
+ # pyroute2 doesn't have support for adding conntrack entries via netlink yet. So, invoking the conntrack utility to add the entries.
+ state = ''
+ if (ipproto == IP_PROTO_TCP):
+ state = ' --state ESTABLISHED '
+ ctcmd = 'conntrack -I -n ' + natdstip + ':' + natdstport + ' -g ' + natsrcip + ':' + natsrcport + \
+ ' --protonum ' + ipproto + state + ' --timeout 600 --src ' + srcip + ' --sport ' + srcport + \
+ ' --dst ' + dstip + ' --dport ' + dstport + ' -u ASSURED'
+ subprocess.call(ctcmd, shell=True)
+ logger.info("Restored NAT entry: {}".format(ctcmd))
+
+# Set the statedb "NAT_RESTORE_TABLE|Flags", so natsyncd can start reconciliation
+def set_statedb_nat_restore_done():
+ statedb = swsscommon.DBConnector(swsscommon.STATE_DB, REDIS_SOCK, 0)
+ tbl = swsscommon.Table(statedb, "NAT_RESTORE_TABLE")
+ fvs = swsscommon.FieldValuePairs([("restored", "true")])
+ tbl.set("Flags", fvs)
+ return
+
+# This function is to restore the kernel nat entries based on the saved nat entries.
+def restore_update_kernel_nat_entries(filename):
+ # Read the entries from nat_entries.dump file and add them to kernel
+ conntrack_match_pattern = re.compile(r'{}'.format(MATCH_CONNTRACK_ENTRY))
+ with open(filename, 'r') as fp:
+ for line in fp:
+ ctline = conntrack_match_pattern.findall(line)
+ if not ctline:
+ continue
+ cmdargs = list(ctline.pop(0))
+ proto = cmdargs.pop(0)
+ if proto not in ('tcp', 'udp'):
+ continue
+ add_nat_conntrack_entry_in_kernel(*cmdargs)
+
+def main():
+ logger.info("restore_nat_entries service is started")
+
+ # Use warmstart python binding to check warmstart information
+ warmstart = swsscommon.WarmStart()
+ warmstart.initialize("natsyncd", "nat")
+ warmstart.checkWarmStart("natsyncd", "nat", False)
+
+ # if swss or system warm reboot not enabled, don't run
+ if not warmstart.isWarmStart():
+ logger.info("restore_nat_entries service is skipped as warm restart not enabled")
+ return
+
+ # NAT restart not system warm reboot, set statedb directly
+ if not warmstart.isSystemWarmRebootEnabled():
+ set_statedb_nat_restore_done()
+ logger.info("restore_nat_entries service is done as system warm reboot not enabled")
+ return
+
+ # Program the nat conntrack entries in the kernel by reading the
+ # entries from nat_entries.dump
+ try:
+ restore_update_kernel_nat_entries(WARM_BOOT_FILE_DIR + NAT_WARM_BOOT_FILE)
+ except Exception as e:
+ logger.exception(str(e))
+ sys.exit(1)
+
+ # Remove the dump file after restoration
+ os.remove(WARM_BOOT_FILE_DIR + NAT_WARM_BOOT_FILE)
+
+ # set statedb to signal other processes like natsyncd
+ set_statedb_nat_restore_done()
+ logger.info("restore_nat_entries service is done for system warmreboot")
+ return
+
+if __name__ == '__main__':
+ main()
diff --git a/dockers/docker-nat/start.sh b/dockers/docker-nat/start.sh
new file mode 100755
index 000000000000..e1f303fee6f2
--- /dev/null
+++ b/dockers/docker-nat/start.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+rm -f /var/run/rsyslogd.pid
+rm -f /var/run/nat/*
+
+mkdir -p /var/warmboot/nat
+
+supervisorctl start rsyslogd
+
+supervisorctl start natmgrd
+
+supervisorctl start natsyncd
+
+supervisorctl start restore_nat_entries
+
diff --git a/dockers/docker-nat/supervisord.conf b/dockers/docker-nat/supervisord.conf
new file mode 100644
index 000000000000..839d6f59ab3c
--- /dev/null
+++ b/dockers/docker-nat/supervisord.conf
@@ -0,0 +1,53 @@
+[supervisord]
+logfile_maxbytes=1MB
+logfile_backups=2
+nodaemon=true
+
+[eventlistener:supervisor-proc-exit-listener]
+command=/usr/bin/supervisor-proc-exit-listener --container-name nat
+events=PROCESS_STATE_EXITED
+autostart=true
+autorestart=unexpected
+
+[program:start.sh]
+command=/usr/bin/start.sh
+priority=1
+autostart=true
+autorestart=false
+stdout_logfile=syslog
+stderr_logfile=syslog
+
+[program:rsyslogd]
+command=/usr/sbin/rsyslogd -n
+priority=2
+autostart=false
+autorestart=unexpected
+stdout_logfile=syslog
+stderr_logfile=syslog
+
+[program:natmgrd]
+command=/usr/bin/natmgrd
+priority=3
+autostart=false
+autorestart=false
+stdout_logfile=syslog
+stderr_logfile=syslog
+
+[program:natsyncd]
+command=/usr/bin/natsyncd
+priority=4
+autostart=false
+autorestart=false
+stdout_logfile=syslog
+stderr_logfile=syslog
+
+[program:restore_nat_entries]
+command=/usr/bin/restore_nat_entries.py
+priority=5
+autostart=false
+autorestart=false
+startsecs=0
+startretries=0
+stdout_logfile=syslog
+stderr_logfile=syslog
+
diff --git a/dockers/docker-orchagent/Dockerfile.j2 b/dockers/docker-orchagent/Dockerfile.j2
index 8a66e2adbe43..f95acd48fdbd 100755
--- a/dockers/docker-orchagent/Dockerfile.j2
+++ b/dockers/docker-orchagent/Dockerfile.j2
@@ -20,7 +20,8 @@ RUN apt-get update && \
tcpdump \
libelf1 \
libmnl0 \
- bridge-utils
+ bridge-utils \
+ conntrack
{% if ( CONFIGURED_ARCH == "armhf" or CONFIGURED_ARCH == "arm64" ) %}
## Fix for gcc/python not found in arm docker
diff --git a/dockers/docker-orchagent/base_image_files/monit_swss b/dockers/docker-orchagent/base_image_files/monit_swss
new file mode 100644
index 000000000000..5928dbd4ddb0
--- /dev/null
+++ b/dockers/docker-orchagent/base_image_files/monit_swss
@@ -0,0 +1,43 @@
+###############################################################################
+## Monit configuration for swss container
+## process list:
+## orchagent
+## portsyncd
+## neighsyncd
+## vrfmgrd
+## vlanmgrd
+## intfmgrd
+## portmgrd
+## buffermgrd
+## nbrmgrd
+## vxlanmgrd
+###############################################################################
+check process orchagent matching "/usr/bin/orchagent -d /var/log/swss"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process portsyncd matching "/usr/bin/portsyncd"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process neighsyncd matching "/usr/bin/neighsyncd"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process vrfmgrd matching "/usr/bin/vrfmgrd"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process vlanmgrd matching "/usr/bin/vlanmgrd"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process intfmgrd matching "/usr/bin/intfmgrd"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process portmgrd matching "/usr/bin/portmgrd"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process buffermgrd matching "/usr/bin/buffermgrd -l"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process nbrmgrd matching "/usr/bin/nbrmgrd"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process vxlanmgrd matching "/usr/bin/vxlanmgrd"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/dockers/docker-orchagent/orchagent.sh b/dockers/docker-orchagent/orchagent.sh
index 5e01cd480f52..3352e5fbb7ec 100755
--- a/dockers/docker-orchagent/orchagent.sh
+++ b/dockers/docker-orchagent/orchagent.sh
@@ -4,7 +4,11 @@
# vendor specific code.
export platform=`sonic-cfggen -y /etc/sonic/sonic_version.yml -v asic_type`
-MAC_ADDRESS=`ip link show eth0 | grep ether | awk '{print $2}'`
+MAC_ADDRESS=$(sonic-cfggen -d -v 'DEVICE_METADATA.localhost.mac')
+if [ "$MAC_ADDRESS" == "None" ] || [ -z "$MAC_ADDRESS" ]; then
+ MAC_ADDRESS=$(ip link show eth0 | grep ether | awk '{print $2}')
+ logger "Mac address not found in Device Metadata, Falling back to eth0"
+fi
# Create a folder for SwSS record files
mkdir -p /var/log/swss
diff --git a/dockers/docker-orchagent/supervisord.conf b/dockers/docker-orchagent/supervisord.conf
index 9ae2776f6d26..6b21d73f3c81 100644
--- a/dockers/docker-orchagent/supervisord.conf
+++ b/dockers/docker-orchagent/supervisord.conf
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name swss
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
diff --git a/dockers/docker-orchagent/swssconfig.sh b/dockers/docker-orchagent/swssconfig.sh
index c521fadf0a49..856b3bcd0e41 100755
--- a/dockers/docker-orchagent/swssconfig.sh
+++ b/dockers/docker-orchagent/swssconfig.sh
@@ -43,11 +43,11 @@ HWSKU=`sonic-cfggen -d -v "DEVICE_METADATA['localhost']['hwsku']"`
# Don't load json config if system warm start or
# swss docker warm start is enabled, the data already exists in appDB.
-SYSTEM_WARM_START=`redis-cli -n 6 hget "WARM_RESTART_ENABLE_TABLE|system" enable`
-SWSS_WARM_START=`redis-cli -n 6 hget "WARM_RESTART_ENABLE_TABLE|swss" enable`
+SYSTEM_WARM_START=`sonic-db-cli STATE_DB hget "WARM_RESTART_ENABLE_TABLE|system" enable`
+SWSS_WARM_START=`sonic-db-cli STATE_DB hget "WARM_RESTART_ENABLE_TABLE|swss" enable`
if [[ "$SYSTEM_WARM_START" == "true" ]] || [[ "$SWSS_WARM_START" == "true" ]]; then
# We have to make sure db data has not been flushed.
- RESTORE_COUNT=`redis-cli -n 6 hget "WARM_RESTART_TABLE|orchagent" restore_count`
+ RESTORE_COUNT=`sonic-db-cli STATE_DB hget "WARM_RESTART_TABLE|orchagent" restore_count`
if [[ -n "$RESTORE_COUNT" ]] && [[ "$RESTORE_COUNT" != "0" ]]; then
exit 0
fi
diff --git a/dockers/docker-platform-monitor/Dockerfile.j2 b/dockers/docker-platform-monitor/Dockerfile.j2
index fd11f628559c..61374af7d544 100755
--- a/dockers/docker-platform-monitor/Dockerfile.j2
+++ b/dockers/docker-platform-monitor/Dockerfile.j2
@@ -18,7 +18,8 @@ RUN apt-get update && \
rrdtool \
python-smbus \
ethtool \
- dmidecode
+ dmidecode && \
+ pip install enum34
{% if docker_platform_monitor_debs.strip() -%}
# Copy locally-built Debian package dependencies
diff --git a/dockers/docker-platform-monitor/docker-pmon.supervisord.conf.j2 b/dockers/docker-platform-monitor/docker-pmon.supervisord.conf.j2
index 9a2414c30d05..13ae0e767ab2 100644
--- a/dockers/docker-platform-monitor/docker-pmon.supervisord.conf.j2
+++ b/dockers/docker-platform-monitor/docker-pmon.supervisord.conf.j2
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name pmon
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
diff --git a/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf b/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf
index 4ea84ab11c92..bf9320acc776 100644
--- a/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf
+++ b/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-script]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name radv
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
diff --git a/dockers/docker-router-advertiser/wait_for_intf.sh.j2 b/dockers/docker-router-advertiser/wait_for_intf.sh.j2
index a044df0fc996..980b472b3e0a 100644
--- a/dockers/docker-router-advertiser/wait_for_intf.sh.j2
+++ b/dockers/docker-router-advertiser/wait_for_intf.sh.j2
@@ -1,7 +1,5 @@
#!/usr/bin/env bash
-STATE_DB_IDX="6"
-
VLAN_TABLE_PREFIX="VLAN_TABLE"
function wait_until_iface_ready
@@ -14,7 +12,7 @@ function wait_until_iface_ready
# Wait for the interface to come up
# (i.e., interface is present in STATE_DB and state is "ok")
while true; do
- RESULT=$(redis-cli -n ${STATE_DB_IDX} HGET "${TABLE_PREFIX}|${IFACE}" "state" 2> /dev/null)
+ RESULT=$(sonic-db-cli STATE_DB HGET "${TABLE_PREFIX}|${IFACE}" "state" 2> /dev/null)
if [ x"$RESULT" == x"ok" ]; then
break
fi
diff --git a/dockers/docker-sflow/base_image_files/monit_sflow b/dockers/docker-sflow/base_image_files/monit_sflow
new file mode 100644
index 000000000000..d041f81001ea
--- /dev/null
+++ b/dockers/docker-sflow/base_image_files/monit_sflow
@@ -0,0 +1,7 @@
+###############################################################################
+## Monit configuration for sflow container
+## process list:
+## sflowmgrd
+###############################################################################
+check process sflowmgrd matching "/usr/bin/sflowmgrd"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/dockers/docker-sflow/supervisord.conf b/dockers/docker-sflow/supervisord.conf
index 50986f197d88..8eb1bdc05e57 100644
--- a/dockers/docker-sflow/supervisord.conf
+++ b/dockers/docker-sflow/supervisord.conf
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name sflow
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
diff --git a/dockers/docker-snmp-sv2/base_image_files/monit_snmp b/dockers/docker-snmp-sv2/base_image_files/monit_snmp
new file mode 100644
index 000000000000..811f9d14b3d4
--- /dev/null
+++ b/dockers/docker-snmp-sv2/base_image_files/monit_snmp
@@ -0,0 +1,11 @@
+###############################################################################
+## Monit configuration for snmp container
+## process list:
+## snmpd
+## snmpd_subagent
+###############################################################################
+check process snmpd matching "/usr/sbin/snmpd -f"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process snmp_subagent matching "python3.6 -m sonic_ax_impl"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/dockers/docker-snmp-sv2/snmpd.conf.j2 b/dockers/docker-snmp-sv2/snmpd.conf.j2
index 16d7e5bff79c..7d4022501fbb 100644
--- a/dockers/docker-snmp-sv2/snmpd.conf.j2
+++ b/dockers/docker-snmp-sv2/snmpd.conf.j2
@@ -15,16 +15,10 @@
# Listen for connections on all ip addresses, including eth0, ipv4 lo
#
-{% if snmp_agent_address_1 or snmp_agent_address_2 or snmp_agent_address_3 %}
-{% if snmp_agent_address_1 %}
-agentAddress {{ snmp_agent_address_1 }}
-{% endif %}
-{% if snmp_agent_address_2 %}
-agentAddress {{ snmp_agent_address_2 }}
-{% endif %}
-{% if snmp_agent_address_3 %}
-agentAddress {{ snmp_agent_address_3 }}
-{% endif %}
+{% if SNMP_AGENT_ADDRESS_CONFIG %}
+{% for (agentip, port, vrf) in SNMP_AGENT_ADDRESS_CONFIG %}
+agentAddress {{ agentip }}{% if port %}:{{ port }}{% endif %}{% if vrf %}%{{ vrf }}{% endif %}{{ "" }}
+{% endfor %}
{% else %}
agentAddress udp:161
agentAddress udp6:161
@@ -105,20 +99,32 @@ load 12 10 5
# Note: disabled snmp traps due to side effect of causing snmpd to listen on all ports (0.0.0.0)
#
# send SNMPv1 traps
-{%if v1_trap_dest and v1_trap_dest != 'NotConfigured' %}
-trapsink {{ v1_trap_dest }}
+{% if SNMP_TRAP_CONFIG and SNMP_TRAP_CONFIG['v1TrapDest'] %}
+{% set v1SnmpTrapIp = SNMP_TRAP_CONFIG['v1TrapDest']['DestIp'] %}
+{% set v1SnmpTrapPort = SNMP_TRAP_CONFIG['v1TrapDest']['DestPort'] %}
+{% set v1SnmpTrapVrf = SNMP_TRAP_CONFIG['v1TrapDest']['vrf'] %}
+{% set v1SnmpTrapComm = SNMP_TRAP_CONFIG['v1TrapDest']['Community'] %}
+trapsink {{ v1SnmpTrapIp }}:{{ v1SnmpTrapPort }}{% if v1SnmpTrapVrf != 'None' %}%{{ v1SnmpTrapVrf }}{% endif %} {{ v1SnmpTrapComm }}{{ "" }}
{% else %}
#trapsink localhost public
{% endif %}
# send SNMPv2c traps
-{%if v2_trap_dest and v2_trap_dest != 'NotConfigured' %}
-trap2sink {{ v2_trap_dest }}
+{% if SNMP_TRAP_CONFIG and SNMP_TRAP_CONFIG['v2TrapDest'] %}
+{% set v2SnmpTrapIp = SNMP_TRAP_CONFIG['v2TrapDest']['DestIp'] %}
+{% set v2SnmpTrapPort = SNMP_TRAP_CONFIG['v2TrapDest']['DestPort'] %}
+{% set v2SnmpTrapVrf = SNMP_TRAP_CONFIG['v2TrapDest']['vrf'] %}
+{% set v2SnmpTrapComm = SNMP_TRAP_CONFIG['v2TrapDest']['Community'] %}
+trap2sink {{ v2SnmpTrapIp }}:{{ v2SnmpTrapPort }}{% if v2SnmpTrapVrf != 'None' %}%{{ v2SnmpTrapVrf }}{% endif %} {{ v2SnmpTrapComm }}{{ "" }}
{% else %}
#trap2sink localhost public
{% endif %}
# send SNMPv2c INFORMs
-{%if v3_trap_dest and v3_trap_dest != 'NotConfigured' %}
-informsink {{ v3_trap_dest }}
+{% if SNMP_TRAP_CONFIG and SNMP_TRAP_CONFIG['v3TrapDest'] %}
+{% set v3SnmpTrapIp = SNMP_TRAP_CONFIG['v3TrapDest']['DestIp'] %}
+{% set v3SnmpTrapPort = SNMP_TRAP_CONFIG['v3TrapDest']['DestPort'] %}
+{% set v3SnmpTrapVrf = SNMP_TRAP_CONFIG['v3TrapDest']['vrf'] %}
+{% set v3SnmpTrapComm = SNMP_TRAP_CONFIG['v3TrapDest']['Community'] %}
+trapsink {{ v3SnmpTrapIp }}:{{ v3SnmpTrapPort }}{% if v3SnmpTrapVrf != 'None' %}%{{ v3SnmpTrapVrf }}{% endif %} {{ v3SnmpTrapComm }}{{ "" }}
{% else %}
#informsink localhost public
{% endif %}
diff --git a/dockers/docker-snmp-sv2/start.sh b/dockers/docker-snmp-sv2/start.sh
index 786968cf9d90..6ec3379df58f 100755
--- a/dockers/docker-snmp-sv2/start.sh
+++ b/dockers/docker-snmp-sv2/start.sh
@@ -9,17 +9,6 @@ sonic-cfggen -d -y /etc/sonic/snmp.yml -t /usr/share/sonic/templates/snmpd.conf.
mkdir -p /var/sonic
echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status
-CURRENT_HOSTNAME=`hostname`
-HOSTNAME=`sonic-cfggen -d -v DEVICE_METADATA[\'localhost\'][\'hostname\']`
-
-if [ "$?" == "0" ] && [ "$HOSTNAME" != "" ]; then
- echo $HOSTNAME > /etc/hostname
- hostname -F /etc/hostname
-
- sed -i "/\s$CURRENT_HOSTNAME$/d" /etc/hosts
- echo "127.0.0.1 $HOSTNAME" >> /etc/hosts
-fi
-
rm -f /var/run/rsyslogd.pid
supervisorctl start rsyslogd
diff --git a/dockers/docker-snmp-sv2/supervisord.conf b/dockers/docker-snmp-sv2/supervisord.conf
index 7fd16eec5bbe..992292330552 100644
--- a/dockers/docker-snmp-sv2/supervisord.conf
+++ b/dockers/docker-snmp-sv2/supervisord.conf
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name snmp
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
diff --git a/dockers/docker-sonic-mgmt-framework/rest-server.sh b/dockers/docker-sonic-mgmt-framework/rest-server.sh
index f2a29c9b1ed2..e450f707dfd1 100755
--- a/dockers/docker-sonic-mgmt-framework/rest-server.sh
+++ b/dockers/docker-sonic-mgmt-framework/rest-server.sh
@@ -46,7 +46,5 @@ echo "REST_SERVER_ARGS = $REST_SERVER_ARGS"
export CVL_SCHEMA_PATH=/usr/sbin/schema
-export LIBYANG_EXTENSIONS_PLUGINS_DIR=/usr/lib/x86_64-linux-gnu/libyang/extensions
-export LIBYANG_USER_TYPES_PLUGINS_DIR=/usr/lib/x86_64-linux-gnu/libyang/user_types
exec /usr/sbin/rest_server ${REST_SERVER_ARGS}
diff --git a/dockers/docker-sonic-restapi/Dockerfile.j2 b/dockers/docker-sonic-restapi/Dockerfile.j2
new file mode 100644
index 000000000000..32904531f1fc
--- /dev/null
+++ b/dockers/docker-sonic-restapi/Dockerfile.j2
@@ -0,0 +1,28 @@
+{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %}
+FROM docker-config-engine-stretch
+
+ARG docker_container_name
+RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf
+
+## Make apt-get non-interactive
+ENV DEBIAN_FRONTEND=noninteractive
+
+RUN apt-get update
+
+{% if docker_sonic_restapi_debs.strip() -%}
+# Copy locally-built Debian package dependencies
+{{ copy_files("debs/", docker_sonic_restapi_debs.split(' '), "/debs/") }}
+
+# Install locally-built Debian packages and implicitly install their dependencies
+{{ install_debian_packages( docker_sonic_restapi_debs.split(' ')) }}
+{%- endif %}
+
+## Clean up
+RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y
+
+COPY ["start.sh", "restapi.sh", "/usr/bin/"]
+COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
+COPY ["files/supervisor-proc-exit-listener", "/usr/bin"]
+COPY ["critical_processes", "/etc/supervisor"]
+
+ENTRYPOINT ["/usr/bin/supervisord"]
diff --git a/dockers/docker-sonic-restapi/base_image_files/monit_restapi b/dockers/docker-sonic-restapi/base_image_files/monit_restapi
new file mode 100644
index 000000000000..2e90baf30d57
--- /dev/null
+++ b/dockers/docker-sonic-restapi/base_image_files/monit_restapi
@@ -0,0 +1,7 @@
+###############################################################################
+## Monit configuration for restapi container
+## process list:
+## restapi
+###############################################################################
+check process restapi matching "/usr/sbin/go-server-server"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/dockers/docker-sonic-restapi/critical_processes b/dockers/docker-sonic-restapi/critical_processes
new file mode 100644
index 000000000000..3106eaa9410a
--- /dev/null
+++ b/dockers/docker-sonic-restapi/critical_processes
@@ -0,0 +1 @@
+restapi
diff --git a/dockers/docker-sonic-restapi/restapi.sh b/dockers/docker-sonic-restapi/restapi.sh
new file mode 100755
index 000000000000..61778e3245d6
--- /dev/null
+++ b/dockers/docker-sonic-restapi/restapi.sh
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+
+RESTAPI_ARGS=""
+while true
+do
+ client_auth=`sonic-cfggen -d -v "RESTAPI['config']['client_auth']"`
+ if [[ $client_auth == 'true' ]]; then
+ certs=`sonic-cfggen -d -v "RESTAPI['certs']"`
+ allow_insecure=`sonic-cfggen -d -v "RESTAPI['config']['allow_insecure']"`
+ if [[ $allow_insecure == 'true' ]]; then
+ RESTAPI_ARGS=" -enablehttp=true"
+ else
+ RESTAPI_ARGS=" -enablehttp=false"
+ fi
+ if [[ -n "$certs" ]]; then
+ SERVER_CRT=`sonic-cfggen -d -v "RESTAPI['certs']['server_crt']"`
+ SERVER_KEY=`sonic-cfggen -d -v "RESTAPI['certs']['server_key']"`
+ CLIENT_CA_CRT=`sonic-cfggen -d -v "RESTAPI['certs']['client_ca_crt']"`
+ CLIENT_CRT_CNAME=`sonic-cfggen -d -v "RESTAPI['certs']['client_crt_cname']"`
+ if [[ -f $SERVER_CRT && -f $SERVER_KEY && -f $CLIENT_CA_CRT ]]; then
+ RESTAPI_ARGS+=" -enablehttps=true -servercert=$SERVER_CRT -serverkey=$SERVER_KEY -clientcert=$CLIENT_CA_CRT -clientcertcommonname=$CLIENT_CRT_CNAME"
+ break
+ fi
+ fi
+ fi
+ logger "Waiting for certificates..."
+ sleep 60
+done
+
+LOG_LEVEL=`sonic-cfggen -d -v "RESTAPI['config']['log_level']"`
+if [ ! -z $LOG_LEVEL ]; then
+ RESTAPI_ARGS+=" -loglevel=$LOG_LEVEL"
+else
+ RESTAPI_ARGS+=" -loglevel=trace"
+fi
+
+logger "RESTAPI_ARGS: $RESTAPI_ARGS"
+exec /usr/sbin/go-server-server ${RESTAPI_ARGS}
diff --git a/dockers/docker-sonic-restapi/start.sh b/dockers/docker-sonic-restapi/start.sh
new file mode 100755
index 000000000000..bff56a8864c1
--- /dev/null
+++ b/dockers/docker-sonic-restapi/start.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+mkdir -p /var/sonic
+echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status
+
+rm -f /var/run/rsyslogd.pid
+
+supervisorctl start rsyslogd
+supervisorctl start restapi
diff --git a/dockers/docker-sonic-restapi/supervisord.conf b/dockers/docker-sonic-restapi/supervisord.conf
new file mode 100644
index 000000000000..58afc6dcd7de
--- /dev/null
+++ b/dockers/docker-sonic-restapi/supervisord.conf
@@ -0,0 +1,34 @@
+[supervisord]
+logfile_maxbytes=1MB
+logfile_backups=2
+nodaemon=true
+
+[eventlistener:supervisor-proc-exit-listener]
+command=/usr/bin/supervisor-proc-exit-listener --container-name restapi
+events=PROCESS_STATE_EXITED
+autostart=true
+autorestart=false
+
+[program:start.sh]
+command=/usr/bin/start.sh
+priority=1
+autostart=true
+autorestart=false
+stdout_logfile=syslog
+stderr_logfile=syslog
+
+[program:restapi]
+command=/usr/bin/restapi.sh
+priority=1
+autostart=false
+autorestart=true
+stdout_logfile=syslog
+stderr_logfile=syslog
+
+[program:rsyslogd]
+command=/usr/sbin/rsyslogd -n
+priority=2
+autostart=false
+autorestart=true
+stdout_logfile=syslog
+stderr_logfile=syslog
diff --git a/dockers/docker-sonic-telemetry/base_image_files/monit_telemetry b/dockers/docker-sonic-telemetry/base_image_files/monit_telemetry
new file mode 100644
index 000000000000..555822c57f80
--- /dev/null
+++ b/dockers/docker-sonic-telemetry/base_image_files/monit_telemetry
@@ -0,0 +1,11 @@
+###############################################################################
+## Monit configuration for telemetry container
+## process list:
+## telemetry
+## dialout_client
+###############################################################################
+check process telemetry matching "/usr/sbin/telemetry -logtostderr --insecure"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process dialout_client matching "/usr/sbin/dialout_client_cli -insecure -logtostderr"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/dockers/docker-sonic-telemetry/supervisord.conf b/dockers/docker-sonic-telemetry/supervisord.conf
index e1346fe7db4e..54f4c5b2348d 100644
--- a/dockers/docker-sonic-telemetry/supervisord.conf
+++ b/dockers/docker-sonic-telemetry/supervisord.conf
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name telemetry
events=PROCESS_STATE_EXITED
autostart=true
autorestart=false
diff --git a/dockers/docker-sonic-telemetry/telemetry.sh b/dockers/docker-sonic-telemetry/telemetry.sh
index 8b29b4d616a5..b8f7fffb3ebb 100755
--- a/dockers/docker-sonic-telemetry/telemetry.sh
+++ b/dockers/docker-sonic-telemetry/telemetry.sh
@@ -1,35 +1,47 @@
#!/usr/bin/env bash
-# Try to read telemetry and x509 config from ConfigDB.
+# Try to read telemetry and certs config from ConfigDB.
# Use default value if no valid config exists
X509=`sonic-cfggen -d -v "DEVICE_METADATA['x509']"`
-TELEMETRY=`sonic-cfggen -d -v 'TELEMETRY.keys() | join(" ") if TELEMETRY'`
+gnmi=`sonic-cfggen -d -v "TELEMETRY['gnmi']"`
+certs=`sonic-cfggen -d -v "TELEMETRY['certs']"`
TELEMETRY_ARGS=" -logtostderr"
export CVL_SCHEMA_PATH=/usr/sbin/schema
-if [ -n "$X509" ]; then
- SERVER_CRT=`sonic-cfggen -d -v "DEVICE_METADATA['x509']['server_crt']"`
- SERVER_KEY=`sonic-cfggen -d -v "DEVICE_METADATA['x509']['server_key']"`
- if [ -z $SERVER_CRT ] || [ -z $SERVER_KEY ]; then
- TELEMETRY_ARGS+=" --insecure"
- else
+if [ -n "$certs" ]; then
+ SERVER_CRT=`sonic-cfggen -d -v "TELEMETRY['certs']['server_crt']"`
+ SERVER_KEY=`sonic-cfggen -d -v "TELEMETRY['certs']['server_key']"`
+ if [ -z $SERVER_CRT ] || [ -z $SERVER_KEY ]; then
+ TELEMETRY_ARGS+=" --insecure"
+ else
+ TELEMETRY_ARGS+=" --server_crt $SERVER_CRT --server_key $SERVER_KEY "
+ fi
+
+ CA_CRT=`sonic-cfggen -d -v "TELEMETRY['certs']['ca_crt']"`
+ if [ ! -z $CA_CRT ]; then
+ TELEMETRY_ARGS+=" --ca_crt $CA_CRT"
+ fi
+elif [ -n "$X509" ]; then
+ SERVER_CRT=`sonic-cfggen -d -v "DEVICE_METADATA['x509']['server_crt']"`
+ SERVER_KEY=`sonic-cfggen -d -v "DEVICE_METADATA['x509']['server_key']"`
+ if [ -z $SERVER_CRT ] || [ -z $SERVER_KEY ]; then
+ TELEMETRY_ARGS+=" --insecure"
+ else
TELEMETRY_ARGS+=" --server_crt $SERVER_CRT --server_key $SERVER_KEY "
fi
-else
- TELEMETRY_ARGS+=" --insecure"
-fi
-if [ -n "$X509" ]; then
- CA_CRT=`sonic-cfggen -d -v "DEVICE_METADATA['x509']['ca_crt']"`
- if [ ! -z $CA_CRT ]; then
- TELEMETRY_ARGS+=" --ca_crt $CA_CRT"
- fi
+ CA_CRT=`sonic-cfggen -d -v "DEVICE_METADATA['x509']['ca_crt']"`
+ if [ ! -z $CA_CRT ]; then
+ TELEMETRY_ARGS+=" --ca_crt $CA_CRT"
+ fi
+else
+ TELEMETRY_ARGS+=" --insecure"
fi
# If no configuration entry exists for TELEMETRY, create one default port
-if [ -z $TELEMETRY ]; then
- redis-cli -n 4 hset "TELEMETRY|gnmi" port 8080
+if [ -z "$gnmi" ]; then
+ sonic-db-cli CONFIG_DB hset "TELEMETRY|gnmi" port 8080
fi
PORT=`sonic-cfggen -d -v "TELEMETRY['gnmi']['port']"`
@@ -37,14 +49,14 @@ TELEMETRY_ARGS+=" --port $PORT"
CLIENT_AUTH=`sonic-cfggen -d -v "TELEMETRY['gnmi']['client_auth']"`
if [ -z $CLIENT_AUTH ] || [ $CLIENT_AUTH == "false" ]; then
- TELEMETRY_ARGS+=" --allow_no_client_auth"
+ TELEMETRY_ARGS+=" --allow_no_client_auth"
fi
LOG_LEVEL=`sonic-cfggen -d -v "TELEMETRY['gnmi']['log_level']"`
if [ ! -z $LOG_LEVEL ]; then
- TELEMETRY_ARGS+=" -v=$LOG_LEVEL"
+ TELEMETRY_ARGS+=" -v=$LOG_LEVEL"
else
- TELEMETRY_ARGS+=" -v=2"
+ TELEMETRY_ARGS+=" -v=2"
fi
exec /usr/sbin/telemetry ${TELEMETRY_ARGS}
diff --git a/dockers/docker-teamd/supervisord.conf b/dockers/docker-teamd/supervisord.conf
index 3a420e0fcdcf..0c3071bbfdda 100644
--- a/dockers/docker-teamd/supervisord.conf
+++ b/dockers/docker-teamd/supervisord.conf
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name teamd
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
@@ -36,6 +36,7 @@ stderr_logfile=syslog
[program:teamsyncd]
command=/usr/bin/teamsyncd
priority=3
+startsecs=5
autostart=false
autorestart=false
stdout_logfile=syslog
diff --git a/files/Aboot/boot0.j2 b/files/Aboot/boot0.j2
index 66e86774e766..3c61c631af93 100644
--- a/files/Aboot/boot0.j2
+++ b/files/Aboot/boot0.j2
@@ -216,9 +216,31 @@ EOF
chmod a+r "${target_path}/machine.conf"
}
+in_array() {
+ local value="$1"
+ shift
+
+ for other in $@; do
+ if [ "$value" = "$other" ]; then
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+read_system_eeprom() {
+ if [ -x /bin/readprefdl ]; then
+ readprefdl -f /tmp/.system-prefdl -d > $target_path/.system-prefdl
+ elif [ -f /etc/prefdl ]; then
+ cp /etc/prefdl $target_path/.system-prefdl
+ chmod a+r $target_path/.system-prefdl
+ fi
+}
+
platform_specific() {
- local platform="$(grep -Eo 'platform=[^ ]+' "$cmdline_base" | cut -f2 -d=)"
- local sid="$(grep -Eo 'sid=[^ ]+' "$cmdline_base" | cut -f2 -d=)"
+ local platform="$(sed -nr 's/.*platform=([^ ]+).*/\1/p' "$cmdline_base")"
+ local sid="$(sed -nr 's/.*sid=([^ ]+).*/\1/p' "$cmdline_base" | sed 's/Ssd$//')"
# set varlog size to 100MB
local varlog_size=100
@@ -227,31 +249,49 @@ platform_specific() {
local flash_size=$(($(df | grep -E "$flash_re" | tr -s ' ' | cut -f2 -d' ') / 1000))
if [ "$platform" = "raven" ]; then
+ # Assuming sid=Cloverdale
aboot_machine=arista_7050_qx32
flash_size=2000
docker_inram=on
echo "modprobe.blacklist=radeon,sp5100_tco acpi=off docker_inram=on" >>/tmp/append
fi
if [ "$platform" = "crow" ]; then
+ # Assuming sid=Clearlake
aboot_machine=arista_7050_qx32s
flash_size=3700
echo "modprobe.blacklist=radeon,sp5100_tco" >>/tmp/append
fi
- if [ "$sid" = "Upperlake" ] || [ "$sid" = "UpperlakeES" ] ||
- [ "$sid" = "UpperlakeSsd" ]; then
+ if [ "$sid" = "Upperlake" ] || [ "$sid" = "UpperlakeES" ]; then
aboot_machine=arista_7060_cx32s
flash_size=3700
- echo "amd_iommu=off" >> /tmp/append
fi
- if [ "$sid" = "Gardena" ] || [ "$sid" = "GardenaSsd" ]; then
+ if [ "$sid" = "UpperlakePlus" ]; then
+ aboot_machine=arista_7060cx2_32s
+ flash_size=3700
+ fi
+ if [ "$sid" = "Gardena" ] || [ "$sid" = "GardenaE" ]; then
aboot_machine=arista_7260cx3_64
flash_size=28000
fi
- if [ "$sid" = "Alhambra" ] || [ "$sid" = "AlhambraSsd" ]; then
+ if [ "$sid" = "Alhambra" ]; then
aboot_machine=arista_7170_64c
flash_size=28000
echo "hugepages=128" >> /tmp/append
fi
+ if [ "$sid" = "Mineral" ]; then
+ aboot_machine=arista_7170_32c
+ flash_size=28000
+ echo "hugepages=128" >> /tmp/append
+ fi
+ if [ "$sid" = "MineralD" ]; then
+ aboot_machine=arista_7170_32cd
+ flash_size=28000
+ echo "hugepages=128" >> /tmp/append
+ fi
+ if [ "$sid" = "Lodoga" ]; then
+ aboot_machine=arista_7050cx3_32s
+ flash_size=3700
+ fi
if [ "$sid" = "BlackhawkO" ]; then
aboot_machine=arista_7060px4_32
flash_size=28000
@@ -260,35 +300,30 @@ platform_specific() {
aboot_machine=arista_7060dx4_32
flash_size=28000
fi
- if [ "$sid" = "Smartsville" ] || [ "$sid" = "SmartsvilleSsd" ]; then
+ if [ "$sid" = "Smartsville" ]; then
aboot_machine=arista_7280cr3_32p4
flash_size=7382
fi
- if [ "$sid" = "SmartsvilleBK" ] || [ "$sid" = "SmartsvilleBKSsd" ]; then
+ if [ "$sid" = "SmartsvilleBK" ]; then
aboot_machine=arista_7280cr3k_32p4
flash_size=7382
fi
- if [ "$sid" = "SmartsvilleDD" ] || [ "$sid" = "SmartsvilleDDSsd" ]; then
+ if [ "$sid" = "SmartsvilleDD" ]; then
aboot_machine=arista_7280cr3_32d4
flash_size=7382
fi
- if [ "$platform" = "rook" ] || [ "$platform" = "magpie" ] ||
- [ "$platform" = "woodpecker" ]; then
+ if in_array "$platform" "rook" "magpie" "woodpecker"; then
echo "tsc=reliable pcie_ports=native" >>/tmp/append
echo "rhash_entries=1 usb-storage.delay_use=0" >>/tmp/append
- if [ -x /bin/readprefdl ]; then
- readprefdl -f /tmp/.system-prefdl -d > /mnt/flash/.system-prefdl
- elif [ -f /etc/prefdl ]; then
- cp /etc/prefdl /mnt/flash/.system-prefdl
- chmod a+r /mnt/flash/.system-prefdl
- fi
echo "reassign_prefmem" >> /tmp/append
fi
- if [ "$platform" = "rook" ] || [ "$platform" = "magpie" ]; then
+ if in_array "$platform" "rook"; then
echo "iommu=on intel_iommu=on" >>/tmp/append
+ read_system_eeprom
fi
- if [ "$platform" = "woodpecker" ]; then
+ if in_array "$platform" "crow" "woodpecker" "magpie"; then
echo "amd_iommu=off modprobe.blacklist=snd_hda_intel,hdaudio" >> /tmp/append
+ read_system_eeprom
fi
if [ $flash_size -ge 28000 ]; then
@@ -358,11 +393,12 @@ write_boot_configs() {
mkdir -p "$image_path"
cat /tmp/append > $cmdline_image
- [ -e ${target_path}/machine.conf ] || write_machine_config
+ [ -s ${target_path}/machine.conf ] || write_machine_config
+ sync
}
run_kexec() {
- local cmdline="$(cat $cmdline_image | tr '\n' ' ')"
+ local cmdline="$(cat $cmdline_image | tr '\n' ' ') $ENV_EXTRA_CMDLINE"
local kernel="${KERNEL:-$(find $image_path/boot -name 'vmlinuz-*' -type f | head -n 1)}"
local initrd="${INITRD:-$(find $image_path/boot -name 'initrd.img-*' -type f | head -n 1)}"
diff --git a/files/apt/apt.conf.d/no-check-valid-until b/files/apt/apt.conf.d/no-check-valid-until
index 97b9c9005181..c7c25d017f7f 100644
--- a/files/apt/apt.conf.d/no-check-valid-until
+++ b/files/apt/apt.conf.d/no-check-valid-until
@@ -1 +1,4 @@
+# Instruct apt-get to NOT check the "Valid Until" date in Release files
+# Once the Debian team archives a repo, they stop updating this date
+
Acquire::Check-Valid-Until "false";
diff --git a/files/build_templates/config-setup.service.j2 b/files/build_templates/config-setup.service.j2
new file mode 100644
index 000000000000..a4b614a5f7fb
--- /dev/null
+++ b/files/build_templates/config-setup.service.j2
@@ -0,0 +1,18 @@
+[Unit]
+Description=Config initialization and migration service
+After=rc-local.service
+After=database.service
+Requires=database.service
+{% if sonic_asic_platform == 'mellanox' -%}
+Requires=hw-management.service
+{% endif -%}
+
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/config-setup boot
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/files/build_templates/database.service.j2 b/files/build_templates/database.service.j2
deleted file mode 100644
index 472b9d328b7d..000000000000
--- a/files/build_templates/database.service.j2
+++ /dev/null
@@ -1,14 +0,0 @@
-[Unit]
-Description=Database container
-Requires=docker.service
-After=docker.service
-After=rc-local.service
-
-[Service]
-User=root
-ExecStartPre=/usr/bin/{{docker_container_name}}.sh start
-ExecStart=/usr/bin/{{docker_container_name}}.sh wait
-ExecStop=/usr/bin/{{docker_container_name}}.sh stop
-
-[Install]
-WantedBy=multi-user.target
diff --git a/files/build_templates/database.service.j2 b/files/build_templates/database.service.j2
new file mode 120000
index 000000000000..63340abef881
--- /dev/null
+++ b/files/build_templates/database.service.j2
@@ -0,0 +1 @@
+per_namespace/database.service.j2
\ No newline at end of file
diff --git a/files/build_templates/docker_image_ctl.j2 b/files/build_templates/docker_image_ctl.j2
index 167a392730e4..297c9dd1c2bd 100644
--- a/files/build_templates/docker_image_ctl.j2
+++ b/files/build_templates/docker_image_ctl.j2
@@ -1,34 +1,35 @@
#!/bin/bash
-function getMountPoint()
-{
- echo $1 | python -c "import sys, json, os; mnts = [x for x in json.load(sys.stdin)[0]['Mounts'] if x['Destination'] == '/usr/share/sonic/hwsku']; print '' if len(mnts) == 0 else os.path.basename(mnts[0]['Source'])" 2>/dev/null
-}
+# single instance containers are still supported (even though it might not look like it)
+# if no instance number is passed to this script, $DEV will simply be unset, resulting in docker
+# commands being sent to the base container name. E.g. `docker start database$DEV` simply starts
+# the container `database` if no instance number is passed since `$DEV` is not defined
-function updateHostName()
-{
- HOSTS=/etc/hosts
- HOSTS_TMP=/etc/hosts.tmp
- EXEC="docker exec -i {{docker_container_name}} bash -c"
+{%- if docker_container_name == "database" %}
+link_namespace() {
+ # Makes namespace of a docker container available in
+ # /var/run/netns so it can be managed with iproute2
+
+ mkdir -p /var/run/netns
+ PID="$(docker inspect -f {{"'{{.State.Pid}}'"}} "{{docker_container_name}}$DEV")"
- NEW_HOSTNAME="$1"
- HOSTNAME=`$EXEC "hostname"`
- if ! [[ $HOSTNAME =~ ^[a-zA-Z0-9.\-]*$ ]]; then
- HOSTNAME=`hostname`
+ PIDS=`ip netns pids "$NET_NS" 2>/dev/null`
+ if [ "$?" -eq "0" ]; then # namespace exists
+ if `echo $PIDS | grep --quiet -w $PID`; then # namespace is correctly linked
+ return 0
+ else # if it's incorrectly linked remove it
+ ip netns delete $NET_NS
+ fi
fi
- # copy HOSTS to HOSTS_TMP
- $EXEC "cp $HOSTS $HOSTS_TMP"
- # remove entry with hostname
- $EXEC "sed -i \"/$HOSTNAME$/d\" $HOSTS_TMP"
- # add entry with new hostname
- $EXEC "echo -e \"127.0.0.1\t$NEW_HOSTNAME\" >> $HOSTS_TMP"
+ ln -s /proc/$PID/ns/net /var/run/netns/$NET_NS
+}
+{%- endif %}
- echo "Set hostname in {{docker_container_name}} container"
- $EXEC "hostname '$NEW_HOSTNAME'"
- $EXEC "cat $HOSTS_TMP > $HOSTS"
- $EXEC "rm -f $HOSTS_TMP"
+function getMountPoint()
+{
+ echo $1 | python -c "import sys, json, os; mnts = [x for x in json.load(sys.stdin)[0]['Mounts'] if x['Destination'] == '/usr/share/sonic/hwsku']; print '' if len(mnts) == 0 else os.path.basename(mnts[0]['Source'])" 2>/dev/null
}
function getBootType()
@@ -56,81 +57,14 @@ function preStartAction()
WARM_DIR=/host/warmboot
if [[ ("$BOOT_TYPE" == "warm" || "$BOOT_TYPE" == "fastfast") && -f $WARM_DIR/dump.rdb ]]; then
# Load redis content from /host/warmboot/dump.rdb
- docker cp $WARM_DIR/dump.rdb database:/var/lib/redis/dump.rdb
+ docker cp $WARM_DIR/dump.rdb database$DEV:/var/lib/redis/dump.rdb
else
# Create an emtpy file and overwrite any RDB if already there
echo -n > /tmp/dump.rdb
- docker cp /tmp/dump.rdb database:/var/lib/redis/
+ docker cp /tmp/dump.rdb database$DEV:/var/lib/redis/
fi
{%- elif docker_container_name == "snmp" %}
- docker exec -i database redis-cli -n 6 HSET 'DEVICE_METADATA|localhost' chassis_serial_number $(decode-syseeprom -s)
- vrfenabled=`/usr/bin/redis-cli -n 4 hget "MGMT_VRF_CONFIG|vrf_global" mgmtVrfEnabled`
- v1SnmpTrapIp=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v1TrapDest" DestIp`
- v1SnmpTrapPort=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v1TrapDest" DestPort`
- v1Vrf=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v1TrapDest" vrf`
- v1Comm=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v1TrapDest" Community`
- v2SnmpTrapIp=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v2TrapDest" DestIp`
- v2SnmpTrapPort=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v2TrapDest" DestPort`
- v2Vrf=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v2TrapDest" vrf`
- v2Comm=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v2TrapDest" Community`
- v3SnmpTrapIp=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v3TrapDest" DestIp`
- v3SnmpTrapPort=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v3TrapDest" DestPort`
- v3Vrf=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v3TrapDest" vrf`
- v3Comm=`/usr/bin/redis-cli -n 4 hget "SNMP_TRAP_CONFIG|v3TrapDest" Community`
-
- if [ "${v1SnmpTrapIp}" != "" ]
- then
- if [ "${v1Vrf}" != "None" ]
- then
- sed -i "s/v1_trap_dest:.*/v1_trap_dest: ${v1SnmpTrapIp}:${v1SnmpTrapPort}%${v1Vrf} ${v1Comm}/" "/etc/sonic/snmp.yml"
- else
- sed -i "s/v1_trap_dest:.*/v1_trap_dest: ${v1SnmpTrapIp}:${v1SnmpTrapPort} ${v1Comm}/" "/etc/sonic/snmp.yml"
- fi
- else
- sed -i "s/v1_trap_dest:.*/v1_trap_dest: NotConfigured/" "/etc/sonic/snmp.yml"
- fi
- if [ "${v2SnmpTrapIp}" != "" ]
- then
- if [ "${v2Vrf}" != "None" ]
- then
- sed -i "s/v2_trap_dest:.*/v2_trap_dest: ${v2SnmpTrapIp}:${v2SnmpTrapPort}%${v2Vrf} ${v2Comm}/" "/etc/sonic/snmp.yml"
- else
- sed -i "s/v2_trap_dest:.*/v2_trap_dest: ${v2SnmpTrapIp}:${v2SnmpTrapPort} ${v2Comm}/" "/etc/sonic/snmp.yml"
- fi
- else
- sed -i "s/v2_trap_dest:.*/v2_trap_dest: NotConfigured/" "/etc/sonic/snmp.yml"
- fi
- if [ "${v3SnmpTrapIp}" != "" ]
- then
- if [ "${v3Vrf}" != "None" ]
- then
- sed -i "s/v3_trap_dest:.*/v3_trap_dest: ${v3SnmpTrapIp}:${v3SnmpTrapPort}%${v3Vrf} ${v3Comm}/" "/etc/sonic/snmp.yml"
- else
- sed -i "s/v3_trap_dest:.*/v3_trap_dest: ${v3SnmpTrapIp}:${v3SnmpTrapPort} ${v3Comm}/" "/etc/sonic/snmp.yml"
- fi
- else
- sed -i "s/v3_trap_dest:.*/v3_trap_dest: NotConfigured/" "/etc/sonic/snmp.yml"
- fi
-
- echo -n "" > /tmp/snmpagentaddr.yml
- keys=`/usr/bin/redis-cli -n 4 keys "SNMP_AGENT_ADDRESS_CONFIG|*"`
- count=1
- for key in $keys;do
- ip=`echo $key|cut -d "|" -f2`
- echo -n "snmp_agent_address_$count: $ip" >> /tmp/snmpagentaddr.yml
- port=`echo $key|cut -d "|" -f3`
- if [ -n "$port" ]; then
- echo -n ":$port" >> /tmp/snmpagentaddr.yml
- fi
- vrf=`echo $key|cut -d "|" -f4`
- if [ -n "$vrf" ]; then
- echo -n "%$vrf" >> /tmp/snmpagentaddr.yml
- fi
- echo "" >> /tmp/snmpagentaddr.yml
- count=$((count+1))
- done
- sed -i '/snmp_agent_address_*/d' /etc/sonic/snmp.yml
- cat /tmp/snmpagentaddr.yml >> /etc/sonic/snmp.yml
+ sonic-netns-exec "$NET_NS" sonic-db-cli STATE_DB HSET 'DEVICE_METADATA|localhost' chassis_serial_number $(decode-syseeprom -s)
{%- else %}
: # nothing
{%- endif %}
@@ -139,22 +73,29 @@ function preStartAction()
function postStartAction()
{
{%- if docker_container_name == "database" %}
+ if [ "$DEV" ]; then
+ link_namespace $DEV
+ fi
# Wait until redis starts
- /usr/bin/docker exec database ping_pong_db_insts
+ /usr/bin/docker exec database$DEV ping_pong_db_insts
if [[ ("$BOOT_TYPE" == "warm" || "$BOOT_TYPE" == "fastfast") && -f $WARM_DIR/dump.rdb ]]; then
rm -f $WARM_DIR/dump.rdb
else
- # If there is a config db dump file, load it
- if [ -r /etc/sonic/config_db.json ]; then
- sonic-cfggen -j /etc/sonic/config_db.json --write-to-db
+ # If there is a config_db.json dump file, load it.
+ if [ -r /etc/sonic/config_db$DEV.json ]; then
+ if [ -r /etc/sonic/init_cfg.json ]; then
+ sonic-netns-exec "$NET_NS" sonic-cfggen -j /etc/sonic/init_cfg.json -j /etc/sonic/config_db$DEV.json --write-to-db
+ else
+ sonic-netns-exec "$NET_NS" sonic-cfggen -j /etc/sonic/config_db$DEV.json --write-to-db
+ fi
fi
if [[ "$BOOT_TYPE" == "fast" ]]; then
# set the key to expire in 3 minutes
- redis-cli -n 6 SET "FAST_REBOOT|system" "1" "EX" "180"
+ /usr/bin/sonic-netns-exec "$NET_NS" sonic-db-cli STATE_DB SET "FAST_REBOOT|system" "1" "EX" "180"
fi
- redis-cli -n 4 SET "CONFIG_DB_INITIALIZED" "1"
+ /usr/bin/sonic-netns-exec "$NET_NS" sonic-db-cli CONFIG_DB SET "CONFIG_DB_INITIALIZED" "1"
fi
if [[ -x /usr/bin/db_migrator.py ]]; then
@@ -162,14 +103,14 @@ function postStartAction()
/usr/bin/db_migrator.py -o migrate
fi
{%- elif docker_container_name == "swss" %}
- docker exec swss rm -f /ready # remove cruft
+ docker exec swss$DEV rm -f /ready # remove cruft
if [[ "$BOOT_TYPE" == "fast" ]] && [[ -d /host/fast-reboot ]]; then
- test -e /host/fast-reboot/fdb.json && docker cp /host/fast-reboot/fdb.json swss:/
- test -e /host/fast-reboot/arp.json && docker cp /host/fast-reboot/arp.json swss:/
- test -e /host/fast-reboot/default_routes.json && docker cp /host/fast-reboot/default_routes.json swss:/
+ test -e /host/fast-reboot/fdb.json && docker cp /host/fast-reboot/fdb.json swss$DEV:/
+ test -e /host/fast-reboot/arp.json && docker cp /host/fast-reboot/arp.json swss$DEV:/
+ test -e /host/fast-reboot/default_routes.json && docker cp /host/fast-reboot/default_routes.json swss$DEV:/
rm -fr /host/fast-reboot
fi
- docker exec swss touch /ready # signal swssconfig.sh to go
+ docker exec swss$DEV touch /ready # signal swssconfig.sh to go
{%- elif docker_container_name == "pmon" %}
DEVPATH="/usr/share/sonic/device"
@@ -191,21 +132,17 @@ start() {
BOOT_TYPE=`getBootType`
# Obtain our platform as we will mount directories with these names in each docker
- PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`
+ PLATFORM=`sonic-netns-exec "$NET_NS" sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`
{%- if docker_container_name == "database" %}
# Don't mount HWSKU in {{docker_container_name}} container.
HWSKU=""
{%- else %}
# Obtain our HWSKU as we will mount directories with these names in each docker
- HWSKU=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hwsku"]'`
- HOSTNAME=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hostname"]'`
+ HWSKU=`sonic-netns-exec "$NET_NS" sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hwsku"]'`
{%- endif %}
- if [ -z "$HOSTNAME" ] || ! [[ $HOSTNAME =~ ^[a-zA-Z0-9.\-]*$ ]]; then
- HOSTNAME=`hostname`
- fi
- DOCKERCHECK=`docker inspect --type container {{docker_container_name}} 2>/dev/null`
+ DOCKERCHECK=`docker inspect --type container {{docker_container_name}}$DEV 2>/dev/null`
if [ "$?" -eq "0" ]; then
{%- if docker_container_name == "database" %}
DOCKERMOUNT=""
@@ -214,39 +151,55 @@ start() {
{%- endif %}
if [ x"$DOCKERMOUNT" == x"$HWSKU" ]; then
{%- if docker_container_name == "database" %}
- echo "Starting existing {{docker_container_name}} container"
+ echo "Starting existing {{docker_container_name}}$DEV container"
{%- else %}
- echo "Starting existing {{docker_container_name}} container with HWSKU $HWSKU"
+ echo "Starting existing {{docker_container_name}}$DEV container with HWSKU $HWSKU"
{%- endif %}
preStartAction
- docker start {{docker_container_name}}
- CURRENT_HOSTNAME="$(docker exec {{docker_container_name}} hostname)"
- if [ x"$HOSTNAME" != x"$CURRENT_HOSTNAME" ]; then
- updateHostName "$HOSTNAME"
- fi
+ docker start {{docker_container_name}}$DEV
postStartAction
exit $?
fi
# docker created with a different HWSKU, remove and recreate
- echo "Removing obsolete {{docker_container_name}} container with HWSKU $DOCKERMOUNT"
- docker rm -f {{docker_container_name}}
+ echo "Removing obsolete {{docker_container_name}}$DEV container with HWSKU $DOCKERMOUNT"
+ docker rm -f {{docker_container_name}}$DEV
fi
-{%- if docker_container_name == "database" %}
- echo "Creating new {{docker_container_name}} container"
+ {%- if docker_container_name == "database" %}
+ echo "Creating new {{docker_container_name}}$DEV container"
# if database_config exists in old_config, use it; otherwise use the default one in new image
if [ -f /etc/sonic/old_config/database_config.json ]; then
echo "Use database_config.json from old system..."
mv /etc/sonic/old_config/database_config.json /etc/sonic/
fi
-{%- else %}
- echo "Creating new {{docker_container_name}} container with HWSKU $HWSKU"
+ {%- else %}
+ echo "Creating new {{docker_container_name}}$DEV container with HWSKU $HWSKU"
+ {%- endif %}
+
+ if [ -z "$DEV" ]; then
+ NET="host"
+ else
+ {%- if docker_container_name == "database" %}
+ NET="bridge"
+ {%- else %}
+ NET="container:database$DEV"
+ {%- endif %}
+ fi
+{%- if docker_container_name == "bgp" %}
+ if [ "$DEV" ]; then
+ if [ ! -d "/etc/sonic/frr/$DEV" ]; then
+ mkdir /etc/sonic/frr/$DEV
+ cp -r /etc/sonic/frr/*.conf /etc/sonic/frr/$DEV
+ fi
+ fi
{%- endif %}
{%- if sonic_asic_platform == "mellanox" %}
# TODO: Mellanox will remove the --tmpfs exception after SDK socket path changed in new SDK version
{%- endif %}
docker create {{docker_image_run_opt}} \
+ --net=$NET \
+ --uts=host \{# W/A: this should be set per-docker, for those dockers which really need host's UTS namespace #}
{%- if install_debug_image == "y" %}
-v /src:/src:ro -v /debug:/debug:rw \
{%- endif %}
@@ -256,52 +209,69 @@ start() {
{%- if sonic_asic_platform == "mellanox" %}
{%- if docker_container_name == "syncd" %}
-v /var/log/mellanox/sniffer:/var/log/mellanox/sniffer:rw \
- -v mlnx_sdk_socket:/tmp \
+ -v mlnx_sdk_socket:/var/run/sx_sdk \
+ -v mlnx_sdk_ready:/tmp \
-v /dev/shm:/dev/shm:rw \
+ -e SX_API_SOCKET_FILE=/var/run/sx_sdk/sx_api.sock \
{%- elif docker_container_name == "pmon" %}
-v /var/run/hw-management:/var/run/hw-management:rw \
- -v mlnx_sdk_socket:/tmp \
+ -v mlnx_sdk_socket:/var/run/sx_sdk \
+ -v mlnx_sdk_ready:/tmp \
+ -e SX_API_SOCKET_FILE=/var/run/sx_sdk/sx_api.sock \
-v /dev/shm:/dev/shm:rw \
{%- else %}
--tmpfs /tmp \
{%- endif %}
{%- endif %}
- -v /var/run/redis:/var/run/redis:rw \
+{%- if docker_container_name == "bgp" %}
+ -v /etc/sonic/frr/$DEV:/etc/frr:rw \
+{%- endif %}
+ -v /var/run/redis$DEV:/var/run/redis:rw \
-v /usr/share/sonic/device/$PLATFORM:/usr/share/sonic/platform:ro \
{%- if docker_container_name != "database" %}
- -v /usr/share/sonic/device/$PLATFORM/$HWSKU:/usr/share/sonic/hwsku:ro \
+ -v /usr/share/sonic/device/$PLATFORM/$HWSKU/$DEV:/usr/share/sonic/hwsku:ro \
{%- endif %}
{%- if sonic_asic_platform != "mellanox" %}
--tmpfs /tmp \
{%- endif %}
--tmpfs /var/tmp \
- --hostname "$HOSTNAME" \
- --name={{docker_container_name}} {{docker_image_name}}:latest || {
+ --name={{docker_container_name}}$DEV {{docker_image_name}}:latest || {
echo "Failed to docker run" >&1
exit 4
}
preStartAction
- docker start {{docker_container_name}}
+ docker start {{docker_container_name}}$DEV
postStartAction
}
wait() {
- docker wait {{docker_container_name}}
+ docker wait {{docker_container_name}}$DEV
}
stop() {
- docker stop {{docker_container_name}}
+ docker stop {{docker_container_name}}$DEV
+{%- if docker_container_name == "database" %}
+ if [ "$DEV" ]; then
+ ip netns delete "$NET_NS"
+ fi
+{%- endif %}
}
+OP=$1
+DEV=$2 # namespace/device number to operate on
+if [ "$DEV" ]; then
+ NET_NS="asic$DEV" #name of the network namespace
+else
+ NET_NS=""
+fi
+
case "$1" in
- start|wait|stop|updateHostName)
- cmd=$1
- shift
- $cmd $@
+ start|wait|stop)
+ $1
;;
*)
- echo "Usage: $0 {start|wait|stop|updateHostName new_hostname}"
+ echo "Usage: $0 {start namespace(optional)|wait namespace(optional)|stop namespace(optional)}"
exit 1
;;
esac
diff --git a/files/build_templates/init_cfg.json.j2 b/files/build_templates/init_cfg.json.j2
new file mode 100644
index 000000000000..c187e02762b8
--- /dev/null
+++ b/files/build_templates/init_cfg.json.j2
@@ -0,0 +1,36 @@
+{
+ "DEVICE_METADATA": {
+ "localhost": {
+ "default_bgp_status": {% if shutdown_bgp_on_start == "y" %}"down"{% else %}"up"{% endif %},
+ "default_pfcwd_status": {% if enable_pfcwd_on_start == "y" %}"enable"{% else %}"disable"{% endif %}
+ }
+ },
+ "CRM": {
+ "Config": {
+ "polling_interval": "300",
+{%- for crm_res in ["ipv4_route", "ipv6_route", "ipv4_nexthop", "ipv6_nexthop", "ipv4_neighbor",
+ "ipv6_neighbor", "nexthop_group_member", "nexthop_group", "acl_table",
+ "acl_group", "acl_entry", "acl_counter", "fdb_entry"] %}
+ "{{crm_res}}_threshold_type": "percentage",
+ "{{crm_res}}_low_threshold": "70",
+ "{{crm_res}}_high_threshold": "85"{% if not loop.last %},{% endif -%}
+{% endfor %}
+ }
+ },
+ "FEATURE": {
+{%- for feature in ["sflow", "telemetry"] %}
+ "{{feature}}": {
+ "status": "disabled"
+ }{% if not loop.last %},{% endif -%}
+{% endfor %}
+ },
+ "CONTAINER_FEATURE": {
+{%- for container in ["bgp", "database", "dhcp_relay", "lldp", "nat", "pmon", "radv", "restapi", "sflow",
+ "snmp", "swss", "syncd", "teamd", "telemetry"] %}
+ "{{container}}": {
+ "auto_restart": "disabled",
+ "high_mem_alert": "disabled"
+ }{% if not loop.last %},{% endif -%}
+{% endfor %}
+ }
+}
diff --git a/files/build_templates/mgmt-framework.service.j2 b/files/build_templates/mgmt-framework.service.j2
index d0a030347b51..acc938c13d90 100644
--- a/files/build_templates/mgmt-framework.service.j2
+++ b/files/build_templates/mgmt-framework.service.j2
@@ -1,7 +1,7 @@
[Unit]
Description=Management Framework container
Requires=swss.service
-After=swss.service
+After=swss.service syncd.service
Before=ntp-config.service
[Service]
diff --git a/files/build_templates/lldp.service.j2 b/files/build_templates/nat.service.j2
similarity index 77%
rename from files/build_templates/lldp.service.j2
rename to files/build_templates/nat.service.j2
index 2599fc5c5bdc..79a56f67ca89 100644
--- a/files/build_templates/lldp.service.j2
+++ b/files/build_templates/nat.service.j2
@@ -1,6 +1,6 @@
[Unit]
-Description=LLDP container
-Requires=updategraph.service
+Description=NAT container
+Requires=updategraph.service swss.service
After=updategraph.service swss.service syncd.service
Before=ntp-config.service
StartLimitIntervalSec=1200
@@ -15,4 +15,5 @@ Restart=always
RestartSec=30
[Install]
-WantedBy=multi-user.target
+WantedBy=multi-user.target swss.service
+
diff --git a/files/build_templates/per_namespace/bgp.service.j2 b/files/build_templates/per_namespace/bgp.service.j2
new file mode 100644
index 000000000000..79e9afc4ebc1
--- /dev/null
+++ b/files/build_templates/per_namespace/bgp.service.j2
@@ -0,0 +1,21 @@
+[Unit]
+Description=BGP container
+Requires=database{% if multi_instance == 'true' %}@%i{% endif %}.service
+After=database{% if multi_instance == 'true' %}@%i{% endif %}.service
+Requires=updategraph.service
+After=updategraph.service
+Before=ntp-config.service
+StartLimitIntervalSec=1200
+StartLimitBurst=3
+
+[Service]
+User={{ sonicadmin_user }}
+ExecStartPre=/usr/bin/{{docker_container_name}}.sh start{% if multi_instance == 'true' %} %i{% endif %}
+ExecStart=/usr/bin/{{docker_container_name}}.sh wait{% if multi_instance == 'true' %} %i{% endif %}
+ExecStop=/usr/bin/{{docker_container_name}}.sh stop{% if multi_instance == 'true' %} %i{% endif %}
+
+Restart=always
+RestartSec=30
+
+[Install]
+WantedBy=multi-user.target
diff --git a/files/build_templates/per_namespace/database.service.j2 b/files/build_templates/per_namespace/database.service.j2
new file mode 100644
index 000000000000..396fdc6678c2
--- /dev/null
+++ b/files/build_templates/per_namespace/database.service.j2
@@ -0,0 +1,22 @@
+[Unit]
+Description=Database container
+{% if multi_instance == 'true' %}
+Requires=database.service
+After=database.service
+{% endif %}
+Requires=docker.service
+After=docker.service
+After=rc-local.service
+StartLimitIntervalSec=1200
+StartLimitBurst=3
+
+[Service]
+User=root
+ExecStartPre=/usr/bin/{{docker_container_name}}.sh start{% if multi_instance == 'true' %} %i{% endif %}
+ExecStart=/usr/bin/{{docker_container_name}}.sh wait{% if multi_instance == 'true' %} %i{% endif %}
+ExecStop=/usr/bin/{{docker_container_name}}.sh stop{% if multi_instance == 'true' %} %i{% endif %}
+Restart=always
+RestartSec=30
+
+[Install]
+WantedBy=multi-user.target
diff --git a/files/build_templates/per_namespace/lldp.service.j2 b/files/build_templates/per_namespace/lldp.service.j2
new file mode 100644
index 000000000000..b48675b03202
--- /dev/null
+++ b/files/build_templates/per_namespace/lldp.service.j2
@@ -0,0 +1,22 @@
+[Unit]
+Description=LLDP container
+Requires=database{% if multi_instance == 'true' %}@%i{% endif %}.service
+After=database{% if multi_instance == 'true' %}@%i{% endif %}.service
+After=swss{% if multi_instance == 'true' %}@%i{% endif %}.service
+After=syncd{% if multi_instance == 'true' %}@%i{% endif %}.service
+Requires=updategraph.service
+After=updategraph.service
+Before=ntp-config.service
+StartLimitIntervalSec=1200
+StartLimitBurst=3
+
+[Service]
+User={{ sonicadmin_user }}
+ExecStartPre=/usr/bin/{{docker_container_name}}.sh start{% if multi_instance == 'true' %} %i{% endif %}
+ExecStart=/usr/bin/{{docker_container_name}}.sh wait{% if multi_instance == 'true' %} %i{% endif %}
+ExecStop=/usr/bin/{{docker_container_name}}.sh stop{% if multi_instance == 'true' %} %i{% endif %}
+Restart=always
+RestartSec=30
+
+[Install]
+WantedBy=multi-user.target
diff --git a/files/build_templates/per_namespace/swss.service.j2 b/files/build_templates/per_namespace/swss.service.j2
new file mode 100644
index 000000000000..53d6b4497df7
--- /dev/null
+++ b/files/build_templates/per_namespace/swss.service.j2
@@ -0,0 +1,31 @@
+[Unit]
+Description=switch state service
+Requires=database{% if multi_instance == 'true' %}@%i{% endif %}.service
+After=database{% if multi_instance == 'true' %}@%i{% endif %}.service
+{% if multi_instance == 'true' and sonic_asic_platform == 'vs' %}
+Requires=topology.service
+After=topology.service
+{% endif %}
+{% if sonic_asic_platform == 'broadcom' %}
+Requires=opennsl-modules.service
+{% elif sonic_asic_platform == 'nephos' %}
+Requires=nps-modules-4.9.0-11-2-amd64.service
+{% endif %}
+Requires=updategraph.service
+After=updategraph.service
+After=interfaces-config.service
+Before=ntp-config.service
+StartLimitIntervalSec=1200
+StartLimitBurst=3
+
+[Service]
+User=root
+Environment=sonic_asic_platform={{ sonic_asic_platform }}
+ExecStartPre=/usr/local/bin/swss.sh start{% if multi_instance == 'true' %} %i{% endif %}
+ExecStart=/usr/local/bin/swss.sh wait{% if multi_instance == 'true' %} %i{% endif %}
+ExecStop=/usr/local/bin/swss.sh stop{% if multi_instance == 'true' %} %i{% endif %}
+Restart=always
+RestartSec=30
+
+[Install]
+WantedBy=multi-user.target
diff --git a/files/build_templates/per_namespace/syncd.service.j2 b/files/build_templates/per_namespace/syncd.service.j2
new file mode 100644
index 000000000000..b2922e0d12b6
--- /dev/null
+++ b/files/build_templates/per_namespace/syncd.service.j2
@@ -0,0 +1,33 @@
+[Unit]
+Description=syncd service
+Requires=database{% if multi_instance == 'true' %}@%i{% endif %}.service
+After=database{% if multi_instance == 'true' %}@%i{% endif %}.service
+After=swss{% if multi_instance == 'true' %}@%i{% endif %}.service
+{% if multi_instance == 'true' and sonic_asic_platform == 'vs' %}
+Requires=topology.service
+After=topology.service
+{% endif %}
+{% if sonic_asic_platform == 'broadcom' %}
+Requires=opennsl-modules.service
+After=opennsl-modules.service
+{% elif sonic_asic_platform == 'nephos' %}
+Requires=nps-modules-4.9.0-11-2-amd64.service
+After=nps-modules-4.9.0-11-2-amd64.service
+{% endif %}
+Requires=updategraph.service
+After=updategraph.service
+After=interfaces-config.service
+Before=ntp-config.service
+
+[Service]
+User=root
+Environment=sonic_asic_platform={{ sonic_asic_platform }}
+ExecStartPre=/usr/local/bin/syncd.sh start{% if multi_instance == 'true' %} %i{% endif %}
+ExecStart=/usr/local/bin/syncd.sh wait{% if multi_instance == 'true' %} %i{% endif %}
+ExecStop=/usr/local/bin/syncd.sh stop{% if multi_instance == 'true' %} %i{% endif %}
+{% if sonic_asic_platform == 'mellanox' %}
+TimeoutStartSec=150
+{% endif %}
+
+[Install]
+WantedBy=multi-user.target
diff --git a/files/build_templates/per_namespace/teamd.service.j2 b/files/build_templates/per_namespace/teamd.service.j2
new file mode 100644
index 000000000000..092f9d2ebde2
--- /dev/null
+++ b/files/build_templates/per_namespace/teamd.service.j2
@@ -0,0 +1,19 @@
+[Unit]
+Description=TEAMD container
+After=swss{% if multi_instance == 'true' %}@%i{% endif %}.service
+Requires=updategraph.service
+After=updategraph.service
+Before=ntp-config.service
+StartLimitIntervalSec=1200
+StartLimitBurst=3
+
+[Service]
+User={{ sonicadmin_user }}
+ExecStartPre=/usr/bin/{{docker_container_name}}.sh start{% if multi_instance == 'true' %} %i{% endif %}
+ExecStart=/usr/bin/{{docker_container_name}}.sh wait{% if multi_instance == 'true' %} %i{% endif %}
+ExecStop=/usr/bin/{{docker_container_name}}.sh stop{% if multi_instance == 'true' %} %i{% endif %}
+Restart=always
+RestartSec=30
+
+[Install]
+WantedBy=multi-user.target
diff --git a/files/build_templates/process-reboot-cause.timer b/files/build_templates/process-reboot-cause.timer
new file mode 100644
index 000000000000..222c51a79a03
--- /dev/null
+++ b/files/build_templates/process-reboot-cause.timer
@@ -0,0 +1,9 @@
+[Unit]
+Description=Delays process-reboot-cause until network is stably connected
+
+[Timer]
+OnBootSec=1min 30 sec
+Unit=process-reboot-cause.service
+
+[Install]
+WantedBy=timers.target
diff --git a/files/build_templates/bgp.service.j2 b/files/build_templates/restapi.service.j2
similarity index 77%
rename from files/build_templates/bgp.service.j2
rename to files/build_templates/restapi.service.j2
index 7200a0e3ecf2..df1a50eb56c7 100644
--- a/files/build_templates/bgp.service.j2
+++ b/files/build_templates/restapi.service.j2
@@ -1,5 +1,5 @@
[Unit]
-Description=BGP container
+Description=RestAPI container
Requires=updategraph.service
After=updategraph.service
Before=ntp-config.service
@@ -9,6 +9,8 @@ User={{ sonicadmin_user }}
ExecStartPre=/usr/bin/{{docker_container_name}}.sh start
ExecStart=/usr/bin/{{docker_container_name}}.sh wait
ExecStop=/usr/bin/{{docker_container_name}}.sh stop
+Restart=always
+RestartSec=30
[Install]
-WantedBy=multi-user.target
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2
index 0e6d07fb001a..68cab2feb9cd 100644
--- a/files/build_templates/sonic_debian_extension.j2
+++ b/files/build_templates/sonic_debian_extension.j2
@@ -81,6 +81,10 @@ sudo mkdir -p $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/
sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/ifupdown2_*.deb || \
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f
+# Install ipables (and its dependencies via 'apt-get -y install -f')
+sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/iptables_*.deb || \
+ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f
+
# Install dependencies for SONiC config engine
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install \
python-dev \
@@ -143,6 +147,12 @@ sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install tabulat
sudo dpkg --root=$FILESYSTEM_ROOT -i $python_debs_path/python-sonic-utilities_*.deb || \
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f
+{% if enable_ztp == "y" %}
+# Install ZTP (and its dependencies via 'apt-get -y install -f')
+sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/sonic-ztp_*.deb || \
+ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f
+{% endif %}
+
# SONiC utilities installs bash-completion as a dependency. However, it is disabled by default
# in bash.bashrc, so we copy a version of the file with it enabled here.
sudo cp -f $IMAGE_CONFIGS/bash/bash.bashrc $FILESYSTEM_ROOT/etc/
@@ -163,8 +173,10 @@ sudo LANG=C chroot $FILESYSTEM_ROOT pam-auth-update --remove tacplus
sudo sed -i -e '/^passwd/s/ tacplus//' $FILESYSTEM_ROOT/etc/nsswitch.conf
# Install a custom version of kdump-tools (and its dependencies via 'apt-get -y install -f')
+if [[ $CONFIGURED_ARCH == amd64 ]]; then
sudo DEBIAN_FRONTEND=noninteractive dpkg --root=$FILESYSTEM_ROOT -i $debs_path/kdump-tools_*.deb || \
sudo LANG=C DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=truechroot $FILESYSTEM_ROOT apt-get -q --no-install-suggests --no-install-recommends --force-no install
+fi
# Install custom-built monit package and SONiC configuration files
sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/monit_*.deb || \
@@ -207,6 +219,12 @@ sudo cp $IMAGE_CONFIGS/interfaces/interfaces-config.sh $FILESYSTEM_ROOT/usr/bin/
sudo cp $IMAGE_CONFIGS/interfaces/*.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/
echo "interfaces-config.service" | sudo tee -a $GENERATED_SERVICE_FILE
+# Copy dhcp client configuration template and create an initial configuration
+sudo cp files/dhcp/dhclient.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/
+j2 files/dhcp/dhclient.conf.j2 | sudo tee $FILESYSTEM_ROOT/etc/dhcp/dhclient.conf
+sudo cp files/dhcp/ifupdown2_policy.json $FILESYSTEM_ROOT/etc/network/ifupdown2/policy.d
+sudo cp files/dhcp/90-dhcp6-systcl.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/
+
# Copy initial interfaces configuration file, will be overwritten on first boot
sudo cp $IMAGE_CONFIGS/interfaces/init_interfaces $FILESYSTEM_ROOT/etc/network/interfaces
sudo mkdir -p $FILESYSTEM_ROOT/etc/network/interfaces.d
@@ -223,10 +241,25 @@ sudo LANG=C chroot $FILESYSTEM_ROOT systemctl disable core_uploader.service
sudo cp $IMAGE_CONFIGS/corefile_uploader/core_uploader.py $FILESYSTEM_ROOT/usr/bin/
sudo cp $IMAGE_CONFIGS/corefile_uploader/core_analyzer.rc.json $FILESYSTEM_ROOT_ETC_SONIC/
sudo chmod og-rw $FILESYSTEM_ROOT_ETC_SONIC/core_analyzer.rc.json
-sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install azure-storage
+
+sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install azure-storage-blob
+
+sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install azure-storage-file-share
+
+sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install azure-storage-file-datalake
+
+sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install azure-storage-queue
+
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install watchdog
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install futures
+{% if install_kubernetes == "y" %}
+# Copy kubelet service files
+# Keep it disabled until join, else it continuously restart and as well spew too many
+# non-required log lines wasting syslog resources.
+sudo LANG=C chroot $FILESYSTEM_ROOT systemctl disable kubelet.service
+{% endif %}
+
# Copy the buffer configuration template
sudo cp $BUILD_TEMPLATES/buffers_config.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/
@@ -241,6 +274,13 @@ sudo cp $IMAGE_CONFIGS/hostname/hostname-config.sh $FILESYSTEM_ROOT/usr/bin/
# Copy miscellaneous scripts
sudo cp $IMAGE_CONFIGS/misc/docker-wait-any $FILESYSTEM_ROOT/usr/bin/
+# Copy internal topology configuration scripts
+{%- if sonic_asic_platform == "vs" %}
+sudo cp $IMAGE_CONFIGS/topology/topology.service $FILESYSTEM_ROOT/etc/systemd/system/
+echo "topology.service" | sudo tee -a $GENERATED_SERVICE_FILE
+sudo cp $IMAGE_CONFIGS/topology/topology.sh $FILESYSTEM_ROOT/usr/bin
+{%- endif %}
+
# Copy updategraph script and service file
j2 files/build_templates/updategraph.service.j2 | sudo tee $FILESYSTEM_ROOT/etc/systemd/system/updategraph.service
sudo cp $IMAGE_CONFIGS/updategraph/updategraph $FILESYSTEM_ROOT/usr/bin/
@@ -252,11 +292,15 @@ sudo bash -c "echo dhcp_as_static=true >> $FILESYSTEM_ROOT/etc/sonic/updategraph
{% else %}
sudo bash -c "echo enabled=false > $FILESYSTEM_ROOT/etc/sonic/updategraph.conf"
{% endif %}
-sudo bash -c "echo '{ \"DEVICE_METADATA\": { \"localhost\": { \"default_bgp_status\": {% if shutdown_bgp_on_start == "y" %}\"down\"{% else %}\"up\"{% endif %}, \"default_pfcwd_status\": {% if enable_pfcwd_on_start == "y" %}\"enable\"{% else %}\"disable\"{% endif %} } },
-{%- print ' \\"CRM\\": { \\"Config\\": { \\"polling_interval\\": \\"300\\", ' %}
-{%- for crm_res in ["ipv4_route", "ipv6_route", "ipv4_nexthop", "ipv6_nexthop", "ipv4_neighbor", "ipv6_neighbor", "nexthop_group_member", "nexthop_group", "acl_table", "acl_group", "acl_entry", "acl_counter", "fdb_entry"] -%}
-\"{{crm_res}}_threshold_type\": \"percentage\", \"{{crm_res}}_low_threshold\": \"70\", \"{{crm_res}}_high_threshold\": \"85\"{% if not loop.last %}, {% endif %}
-{%- endfor %} } } }' >> $FILESYSTEM_ROOT/etc/sonic/init_cfg.json"
+
+# Generate initial SONiC configuration file
+j2 files/build_templates/init_cfg.json.j2 | sudo tee $FILESYSTEM_ROOT/etc/sonic/init_cfg.json
+
+# Copy config-setup script and service file
+j2 files/build_templates/config-setup.service.j2 | sudo tee $FILESYSTEM_ROOT/etc/systemd/system/config-setup.service
+sudo cp $IMAGE_CONFIGS/config-setup/config-setup $FILESYSTEM_ROOT/usr/bin/config-setup
+echo "config-setup.service" | sudo tee -a $GENERATED_SERVICE_FILE
+sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable config-setup.service
# Copy SNMP configuration files
sudo cp $IMAGE_CONFIGS/snmp/snmp.yml $FILESYSTEM_ROOT/etc/sonic/
@@ -278,6 +322,11 @@ sudo cp $IMAGE_CONFIGS/procdockerstatsd/procdockerstatsd.service $FILESYSTEM_RO
echo "procdockerstatsd.service" | sudo tee -a $GENERATED_SERVICE_FILE
sudo cp $IMAGE_CONFIGS/procdockerstatsd/procdockerstatsd $FILESYSTEM_ROOT/usr/bin/
+# Copy systemd timer configuration
+# It implements delayed start of services
+sudo cp $BUILD_TEMPLATES/process-reboot-cause.timer $FILESYSTEM_ROOT/etc/systemd/system/
+sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable process-reboot-cause.timer
+
# Copy process-reboot-cause service files
sudo cp $IMAGE_CONFIGS/process-reboot-cause/process-reboot-cause.service $FILESYSTEM_ROOT/etc/systemd/system/
echo "process-reboot-cause.service" | sudo tee -a $GENERATED_SERVICE_FILE
@@ -365,6 +414,18 @@ sudo LANG=C chroot $FILESYSTEM_ROOT docker $SONIC_NATIVE_DOCKERD_FOR_DOCKERFS ta
sudo LANG=C chroot $FILESYSTEM_ROOT docker $SONIC_NATIVE_DOCKERD_FOR_DOCKERFS tag {{imagename}}:latest {{imagebasename}}:latest
{% endif %}
{% endfor %}
+
+{% if install_kubernetes == "y" %}
+## Pull in kubernetes docker images
+echo "pulling universal k8s images ..."
+sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT docker pull k8s.gcr.io/pause:${K8s_GCR_IO_PAUSE_VERSION}
+sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT docker pull k8s.gcr.io/kube-proxy:v${KUBERNETES_VERSION}
+sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT docker pull calico/node:v${K8s_CNI_CALICO_VERSION}
+sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT docker pull calico/pod2daemon-flexvol:v${K8s_CNI_CALICO_VERSION}
+sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT docker pull calico/cni:v${K8s_CNI_CALICO_VERSION}
+echo "docker images pull complete"
+{% endif %}
+
if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then
sudo umount $FILESYSTEM_ROOT/dockerfs
sudo rm -fr $FILESYSTEM_ROOT/dockerfs
@@ -379,6 +440,13 @@ sudo cp {{script}} $FILESYSTEM_ROOT/usr/bin/
{% for service in installer_services.split(' ') -%}
if [ -f {{service}} ]; then
sudo cp {{service}} $FILESYSTEM_ROOT/etc/systemd/system/
+
+ {% if "@" in service %}
+ MULTI_INSTANCE="{{service}}"
+ SINGLE_INSTANCE=${MULTI_INSTANCE/"@"}
+ sudo cp $SINGLE_INSTANCE $FILESYSTEM_ROOT/etc/systemd/system/
+ {% endif %}
+
echo "{{service}}" | sudo tee -a $GENERATED_SERVICE_FILE
fi
{% endfor %}
@@ -390,6 +458,9 @@ sudo LANG=C chroot $FILESYSTEM_ROOT umount -lf /sys
sudo LANG=C cp $SCRIPTS_DIR/swss.sh $FILESYSTEM_ROOT/usr/local/bin/swss.sh
sudo LANG=C cp $SCRIPTS_DIR/syncd.sh $FILESYSTEM_ROOT/usr/local/bin/syncd.sh
+# Copy sonic-netns-exec script
+sudo LANG=C cp $SCRIPTS_DIR/sonic-netns-exec $FILESYSTEM_ROOT/usr/bin/sonic-netns-exec
+
# Copy systemd timer configuration
# It implements delayed start of services
sudo cp $BUILD_TEMPLATES/snmp.timer $FILESYSTEM_ROOT/etc/systemd/system/
@@ -415,8 +486,11 @@ sudo cp {{src}} $FILESYSTEM_ROOT/{{dst}}
sudo mkdir -p $FILESYSTEM_ROOT/etc/mlnx/
sudo cp $files_path/$MLNX_SPC_FW_FILE $FILESYSTEM_ROOT/etc/mlnx/fw-SPC.mfa
sudo cp $files_path/$MLNX_SPC2_FW_FILE $FILESYSTEM_ROOT/etc/mlnx/fw-SPC2.mfa
+sudo cp $files_path/$MLNX_SPC3_FW_FILE $FILESYSTEM_ROOT/etc/mlnx/fw-SPC3.mfa
sudo cp $files_path/$ISSU_VERSION_FILE $FILESYSTEM_ROOT/etc/mlnx/issu-version
sudo cp $files_path/$MLNX_FFB_SCRIPT $FILESYSTEM_ROOT/usr/bin/mlnx-ffb.sh
+sudo cp $files_path/$MLNX_ONIE_FW_UPDATE $FILESYSTEM_ROOT/usr/bin/$MLNX_ONIE_FW_UPDATE
+sudo cp $files_path/$MLNX_SSD_FW_UPDATE $FILESYSTEM_ROOT/usr/bin/$MLNX_SSD_FW_UPDATE
j2 platform/mellanox/mlnx-fw-upgrade.j2 | sudo tee $FILESYSTEM_ROOT/usr/bin/mlnx-fw-upgrade.sh
sudo chmod 755 $FILESYSTEM_ROOT/usr/bin/mlnx-fw-upgrade.sh
diff --git a/files/build_templates/swss.service.j2 b/files/build_templates/swss.service.j2
deleted file mode 100644
index b7a6396749bd..000000000000
--- a/files/build_templates/swss.service.j2
+++ /dev/null
@@ -1,25 +0,0 @@
-[Unit]
-Description=switch state service
-Requires=database.service updategraph.service
-{% if sonic_asic_platform == 'broadcom' %}
-Requires=opennsl-modules.service
-{% elif sonic_asic_platform == 'nephos' %}
-Requires=nps-modules-4.9.0-9-2-amd64.service
-{% endif %}
-After=database.service updategraph.service
-After=interfaces-config.service
-Before=ntp-config.service
-StartLimitIntervalSec=1200
-StartLimitBurst=3
-
-[Service]
-User=root
-Environment=sonic_asic_platform={{ sonic_asic_platform }}
-ExecStartPre=/usr/local/bin/swss.sh start
-ExecStart=/usr/local/bin/swss.sh wait
-ExecStop=/usr/local/bin/swss.sh stop
-Restart=always
-RestartSec=30
-
-[Install]
-WantedBy=multi-user.target
diff --git a/files/build_templates/syncd.service.j2 b/files/build_templates/syncd.service.j2
deleted file mode 100644
index b52772e9b114..000000000000
--- a/files/build_templates/syncd.service.j2
+++ /dev/null
@@ -1,30 +0,0 @@
-[Unit]
-Description=syncd service
-Requires=database.service updategraph.service
-{% if sonic_asic_platform == 'broadcom' %}
-Requires=opennsl-modules.service
-{% elif sonic_asic_platform == 'nephos' %}
-Requires=nps-modules-4.9.0-9-2-amd64.service
-{% endif %}
-After=database.service updategraph.service
-After=interfaces-config.service
-{% if sonic_asic_platform == 'broadcom' %}
-After=opennsl-modules.service
-{% elif sonic_asic_platform == 'nephos' %}
-After=nps-modules-4.9.0-9-2-amd64.service
-{% endif %}
-After=swss.service
-Before=ntp-config.service
-
-[Service]
-User=root
-Environment=sonic_asic_platform={{ sonic_asic_platform }}
-ExecStartPre=/usr/local/bin/syncd.sh start
-ExecStart=/usr/local/bin/syncd.sh wait
-ExecStop=/usr/local/bin/syncd.sh stop
-{% if sonic_asic_platform == 'mellanox' %}
-TimeoutStartSec=150
-{% endif %}
-
-[Install]
-WantedBy=multi-user.target
diff --git a/files/build_templates/teamd.service.j2 b/files/build_templates/teamd.service.j2
deleted file mode 100644
index be0521a4fbec..000000000000
--- a/files/build_templates/teamd.service.j2
+++ /dev/null
@@ -1,18 +0,0 @@
-[Unit]
-Description=TEAMD container
-Requires=updategraph.service
-After=updategraph.service swss.service
-Before=ntp-config.service
-StartLimitIntervalSec=1200
-StartLimitBurst=3
-
-[Service]
-User={{ sonicadmin_user }}
-ExecStartPre=/usr/bin/{{docker_container_name}}.sh start
-ExecStart=/usr/bin/{{docker_container_name}}.sh wait
-ExecStop=/usr/bin/{{docker_container_name}}.sh stop
-Restart=always
-RestartSec=30
-
-[Install]
-WantedBy=multi-user.target
diff --git a/files/build_templates/updategraph.service.j2 b/files/build_templates/updategraph.service.j2
index 8039f42531cd..0e05cbf147d6 100644
--- a/files/build_templates/updategraph.service.j2
+++ b/files/build_templates/updategraph.service.j2
@@ -1,12 +1,7 @@
[Unit]
Description=Update minigraph and set configuration based on minigraph
-After=rc-local.service
-After=database.service
-Requires=database.service
-{% if sonic_asic_platform == 'mellanox' -%}
-Requires=hw-management.service
-{% endif -%}
-
+After=config-setup.service
+Requires=config-setup.service
[Service]
Type=oneshot
diff --git a/files/dhcp/90-dhcp6-systcl.conf.j2 b/files/dhcp/90-dhcp6-systcl.conf.j2
new file mode 100644
index 000000000000..addb94675258
--- /dev/null
+++ b/files/dhcp/90-dhcp6-systcl.conf.j2
@@ -0,0 +1,7 @@
+{% if MGMT_INTERFACE %}
+net.ipv6.conf.eth0.accept_ra_defrtr = 0
+net.ipv6.conf.eth0.accept_ra = 0
+{% else %}
+net.ipv6.conf.eth0.accept_ra_defrtr = 1
+net.ipv6.conf.eth0.accept_ra = 1
+{% endif %}
diff --git a/files/dhcp/dhclient.conf b/files/dhcp/dhclient.conf
deleted file mode 100644
index 6a542e069fab..000000000000
--- a/files/dhcp/dhclient.conf
+++ /dev/null
@@ -1,24 +0,0 @@
-# Configuration file for /sbin/dhclient, which is included in Debian's
-# dhcp3-client package.
-#
-# This is a sample configuration file for dhclient. See dhclient.conf's
-# man page for more information about the syntax of this file
-# and a more comprehensive list of the parameters understood by
-# dhclient.
-#
-# Normally, if the DHCP server provides reasonable information and does
-# not leave anything out (like the domain name, for example), then
-# few changes must be made to this file, if any.
-#
-
-option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
-option snmp-community code 224 = text;
-option minigraph-url code 225 = text;
-option acl-url code 226 = text;
-
-send host-name = gethostname();
-request subnet-mask, broadcast-address, time-offset, routers,
- domain-name, domain-name-servers, domain-search, host-name,
- dhcp6.name-servers, dhcp6.domain-search, interface-mtu,
- rfc3442-classless-static-routes, ntp-servers,
- snmp-community, minigraph-url, acl-url;
diff --git a/files/dhcp/dhclient.conf.j2 b/files/dhcp/dhclient.conf.j2
new file mode 100644
index 000000000000..2a6f6fa84fbd
--- /dev/null
+++ b/files/dhcp/dhclient.conf.j2
@@ -0,0 +1,45 @@
+{% block banner %}
+# =============== Managed by SONiC Config Engine DO NOT EDIT! ===============
+# generated from /usr/share/sonic/templates/dhclient.conf.j2 using sonic-cfggen
+# file: /etc/dhcp/dhclient.conf
+#
+{% endblock banner %}
+# Configuration file for /sbin/dhclient, which is included in Debian's
+# dhcp3-client package.
+#
+# This is a sample configuration file for dhclient. See dhclient.conf's
+# man page for more information about the syntax of this file
+# and a more comprehensive list of the parameters understood by
+# dhclient.
+#
+# Normally, if the DHCP server provides reasonable information and does
+# not leave anything out (like the domain name, for example), then
+# few changes must be made to this file, if any.
+#
+
+option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
+option snmp-community code 224 = text;
+option minigraph-url code 225 = text;
+option acl-url code 226 = text;
+option tftp-server-name code 66 = text;
+option bootfile-name code 67 = text;
+option user-class code 77 = text;
+option provisioning-script-url code 239 = text;
+option dhcp6.user-class code 15 = text;
+option dhcp6.provisioning-script-url code 239 = text;
+option dhcp6.boot-file-url code 59 = text;
+
+send host-name = gethostname();
+request subnet-mask, broadcast-address, time-offset, routers,
+ domain-name, domain-name-servers, domain-search, host-name,
+ dhcp6.name-servers, dhcp6.domain-search, interface-mtu, dhcp6.fqdn,
+ rfc3442-classless-static-routes, ntp-servers, log-servers,
+{%- if ZTP is defined and ZTP_DHCP_DISABLED is not defined -%}bootfile-name, provisioning-script-url, tftp-server-name,
+ dhcp6.provisioning-script-url, dhcp6.boot-file-url,{%- endif -%}
+ snmp-community, minigraph-url, acl-url;
+{% if ZTP is defined and ZTP_DHCP_DISABLED is not defined %}
+send user-class "SONiC-ZTP";
+send dhcp6.user-class "SONiC-ZTP";
+send dhcp-client-identifier "SONiC##{{ ZTP['mode']['product-name'] }}##{{ ZTP['mode']['serial-no'] }}";
+retry 60;
+{% endif %}
diff --git a/files/dhcp/graphserviceurl b/files/dhcp/graphserviceurl
index f255cdff9877..9bd5fded4b8f 100644
--- a/files/dhcp/graphserviceurl
+++ b/files/dhcp/graphserviceurl
@@ -1,12 +1,14 @@
-case $reason in
- BOUND|RENEW|REBIND|REBOOT)
- if [ -n "$new_minigraph_url" ]; then
- echo $new_minigraph_url > /tmp/dhcp_graph_url
- else
- echo "N/A" > /tmp/dhcp_graph_url
- fi
- if [ -n "$new_acl_url" ]; then
- echo $new_acl_url > /tmp/dhcp_acl_url
- fi
- ;;
-esac
+if [ ! -e /usr/bin/ztp ] || [ "$(ztp status -c)" = "0:DISABLED" ]; then
+ case $reason in
+ BOUND|RENEW|REBIND|REBOOT)
+ if [ -n "$new_minigraph_url" ]; then
+ echo $new_minigraph_url > /tmp/dhcp_graph_url
+ else
+ echo "N/A" > /tmp/dhcp_graph_url
+ fi
+ if [ -n "$new_acl_url" ]; then
+ echo $new_acl_url > /tmp/dhcp_acl_url
+ fi
+ ;;
+ esac
+fi
diff --git a/files/dhcp/ifupdown2_policy.json b/files/dhcp/ifupdown2_policy.json
new file mode 100644
index 000000000000..9a5010dead8a
--- /dev/null
+++ b/files/dhcp/ifupdown2_policy.json
@@ -0,0 +1,12 @@
+{
+ "dhcp" : {
+ "defaults" : {
+ "dhcp-wait" : "no"
+ },
+ "iface_defaults" : {
+ "eth0" : {
+ "dhcp6-duid" : "LL"
+ }
+ }
+ }
+}
diff --git a/files/dhcp/rfc3442-classless-routes b/files/dhcp/rfc3442-classless-routes
index 64e24192816b..797a0d24429f 100644
--- a/files/dhcp/rfc3442-classless-routes
+++ b/files/dhcp/rfc3442-classless-routes
@@ -55,8 +55,13 @@ if [ "$RUN" = "yes" ]; then
fi
# set route (ip detects host routes automatically)
- ip -4 route add "${net_address}/${net_length}" \
+ if echo $interface | grep -v Ethernet ; then
+ ip -4 route add "${net_address}/${net_length}" \
${via_arg} dev "${interface}" table default >/dev/null 2>&1
+ else
+ ip -4 route add "${net_address}/${net_length}" \
+ ${via_arg} dev "${interface}" >/dev/null 2>&1
+ fi
done
fi
fi
diff --git a/files/dhcp/sethostname6 b/files/dhcp/sethostname6
new file mode 100644
index 000000000000..6ca5d8dbc995
--- /dev/null
+++ b/files/dhcp/sethostname6
@@ -0,0 +1,14 @@
+case $reason in
+ BOUND6|RENEW6|REBIND6|REBOOT)
+ current_dhcp6_fqdn=`hostname`
+ if [ "$current_dhcp6_fqdn" != "$new_dhcp6_fqdn" ] && [ -n "$new_dhcp6_fqdn" ]
+ then
+ echo $new_dhcp6_fqdn > /etc/hostname
+ hostname -F /etc/hostname
+ sed -i "/\s$current_dhcp6_fqdn$/d" /etc/hosts
+ sed -i "/\s$new_dhcp6_fqdn$/d" /etc/hosts
+ echo "127.0.0.1 $new_dhcp6_fqdn" >> /etc/hosts
+ echo ":: $new_dhcp6_fqdn" >> /etc/hosts
+ fi
+ ;;
+esac
diff --git a/files/image_config/caclmgrd/caclmgrd b/files/image_config/caclmgrd/caclmgrd
index 6226bb16768f..e5744c7ca65b 100755
--- a/files/image_config/caclmgrd/caclmgrd
+++ b/files/image_config/caclmgrd/caclmgrd
@@ -225,7 +225,9 @@ class ControlPlaneAclManager(object):
rule_cmd = "ip6tables" if table_ip_version == 6 else "iptables"
rule_cmd += " -A INPUT -p {}".format(ip_protocol)
- if "SRC_IP" in rule_props and rule_props["SRC_IP"]:
+ if "SRC_IPV6" in rule_props and rule_props["SRC_IPV6"]:
+ rule_cmd += " -s {}".format(rule_props["SRC_IPV6"])
+ elif "SRC_IP" in rule_props and rule_props["SRC_IP"]:
rule_cmd += " -s {}".format(rule_props["SRC_IP"])
rule_cmd += " --dport {}".format(dst_port)
diff --git a/files/image_config/config-setup/config-setup b/files/image_config/config-setup/config-setup
new file mode 100755
index 000000000000..afff97806518
--- /dev/null
+++ b/files/image_config/config-setup/config-setup
@@ -0,0 +1,398 @@
+#!/bin/bash
+###########################################################################
+# Copyright 2019 Broadcom. The term "Broadcom" refers to Broadcom Inc. #
+# and/or its subsidiaries. #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" BASIS, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.#
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+# #
+###########################################################################
+# SONiC Configuration Setup #
+# #
+# This script is used to initialize configuration used #
+# by SONiC SWSS. It also performs configuration #
+# migration. #
+# #
+###########################################################################
+
+# Initialize constants
+UPDATEGRAPH_CONF=/etc/sonic/updategraph.conf
+CONFIG_DB_JSON=/etc/sonic/config_db.json
+MINGRAPH_FILE=/etc/sonic/minigraph.xml
+TMP_ZTP_CONFIG_DB_JSON=/tmp/ztp_config_db.json
+FACTORY_DEFAULT_HOOKS=/etc/config-setup/factory-default-hooks.d
+CONFIG_PRE_MIGRATION_HOOKS=/etc/config-setup/config-migration-pre-hooks.d
+CONFIG_POST_MIGRATION_HOOKS=/etc/config-setup/config-migration-post-hooks.d
+CONFIG_SETUP_VAR_DIR=/var/lib/config-setup
+CONFIG_SETUP_PRE_MIGRATION_FLAG=${CONFIG_SETUP_VAR_DIR}/pending_pre_migration
+CONFIG_SETUP_POST_MIGRATION_FLAG=${CONFIG_SETUP_VAR_DIR}/pending_post_migration
+CONFIG_SETUP_INITIALIZATION_FLAG=${CONFIG_SETUP_VAR_DIR}/pending_initialization
+
+# Command usage and help
+usage()
+{
+ cat << EOF
+ Usage: config-setup < backup | boot | factory >
+
+ backup - Take a backup copy of SONiC configuration.
+ boot - Initialize/migrate SONiC configuration during system boot.
+ factory - Create factory default SONiC configuration and save it to
+ to ${CONFIG_DB_JSON}.
+EOF
+}
+
+# run given script
+run_hook() {
+ local script="$1"
+ local exit_status=0
+
+ if [ -f $script ]; then
+ # Check hook for syntactical correctness before executing it
+ /bin/bash -n $script
+ exit_status=$?
+ if [ "$exit_status" -eq 0 ]; then
+ . $script
+ fi
+ exit_status=$?
+ fi
+
+ if [ -n "$exit_status" ] && [ "$exit_status" -ne 0 ]; then
+ echo "$script returned non-zero exit status $exit_status"
+ fi
+
+ return $exit_status
+}
+
+# run scripts in given directory
+run_hookdir() {
+ local dir="$1"
+ local progress_file="$2"
+ local exit_status=0
+
+ if [ -d "$dir" ]; then
+ if [ -n $progress_file ]; then
+ [ ! -d $(dirname $progress_file) ] && mkdir -p $(dirname $progress_file)
+ [ ! -e $progress_file ] && run-parts --list $dir > $progress_file
+ SCRIPT_LIST=$(cat $progress_file)
+ else
+ SCRIPT_LIST=$(run-parts --list $dir)
+ fi
+
+ for script in $SCRIPT_LIST; do
+ run_hook $script
+ exit_status=$((exit_status|$?))
+ script_name=$(basename $script)
+ sed -i "/$script_name/d" $progress_file
+ done
+ [ -n $progress_file ] && [ "$(cat ${progress_file})" = "" ] && rm -f ${progress_file}
+ fi
+
+ return $exit_status
+}
+
+# Reload minigraph.xml file on disk
+reload_minigraph()
+{
+ echo "Reloading minigraph..."
+ if [ ! -f /etc/sonic/init_cfg.json ]; then
+ echo "{}" > /etc/sonic/init_cfg.json
+ fi
+ sonic-db-cli CONFIG_DB FLUSHDB
+ sonic-cfggen -H -m -j /etc/sonic/init_cfg.json --write-to-db
+ sonic-db-cli CONFIG_DB SET "CONFIG_DB_INITIALIZED" "1"
+ if [ -f /etc/sonic/acl.json ]; then
+ acl-loader update full /etc/sonic/acl.json
+ fi
+ config qos reload
+ pfcwd start_default
+
+ if [[ -x /usr/bin/db_migrator.py ]]; then
+ # Set latest version number
+ /usr/bin/db_migrator.py -o set_version
+ fi
+}
+
+# Restore SONiC configuration from a backup copy
+function copy_config_files_and_directories()
+{
+ for file_dir in $@; do
+ if [ -f /etc/sonic/old_config/${file_dir} ] || [ -d /etc/sonic/old_config/${file_dir} ]; then
+ echo "Copying SONiC configuration ${file_dir} ..."
+ cp -ar /etc/sonic/old_config/${file_dir} /etc/sonic/
+ else
+ echo "Missing SONiC configuration ${file_dir} ..."
+ fi
+ done
+}
+
+# Check if SONiC swich has booted after a warm reboot request
+check_system_warm_boot()
+{
+ SYSTEM_WARM_START=`sonic-db-cli STATE_DB hget "WARM_RESTART_ENABLE_TABLE|system" enable`
+ # SYSTEM_WARM_START could be empty, always make WARM_BOOT meaningful.
+ if [[ x"$SYSTEM_WARM_START" == x"true" ]]; then
+ WARM_BOOT="true"
+ else
+ WARM_BOOT="false"
+ fi
+}
+
+# Check if updategraph service is administratively enabled
+updategraph_is_enabled()
+{
+ rv=1
+ if [ -e ${UPDATEGRAPH_CONF} ]; then
+ updategraph_mode=$(grep enabled ${UPDATEGRAPH_CONF} | head -n 1 | cut -f2 -d=)
+ [ "${updategraph_mode}" = "true" ] && rv = 0
+ fi
+ return $rv
+}
+
+# Disable updategraph admininistratively
+disable_updategraph()
+{
+ sed -i "/enabled=/d" ${UPDATEGRAPH_CONF}
+ echo "enabled=false" >> ${UPDATEGRAPH_CONF}
+}
+
+# Check if Zero Touch Provisioning is available and is administratively enabled
+ztp_is_enabled()
+{
+ rv=1
+ if [ -e /usr/bin/ztp ]; then
+ status=$(ztp status -c)
+ [ "$status" != "0:DISABLED" ] && [ "$status" != "" ] && rv=0
+ fi
+ return $rv
+}
+
+# Load requested SONiC configuration into config DB and initialize it
+# Usage: load_config
+#
+#
+load_config()
+{
+ CONFIG_FILE=${1}
+ if [ "${CONFIG_FILE}" = "" ]; then
+ return 1
+ fi
+
+ sonic-db-cli CONFIG_DB FLUSHDB
+ sonic-cfggen -j ${CONFIG_FILE} --write-to-db
+ if [ $? -ne 0 ]; then
+ return $?
+ fi
+
+ if [[ -x /usr/bin/db_migrator.py ]]; then
+ # Migrate the DB to the latest schema version if needed
+ /usr/bin/db_migrator.py -o migrate
+ fi
+
+ sonic-db-cli CONFIG_DB SET "CONFIG_DB_INITIALIZED" "1"
+ return 0
+}
+
+
+# Generate requested SONiC configuration and save it as destination file
+# Usage: generate_config < factory | ztp >
+#
+# factory - Create factory default configuration
+# ztp - Create Zero Touch Provisioning Configuration
+# used for provisioning data discovery.
+#
+generate_config()
+{
+ # Collect all information needed to generate configuration
+ PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`
+ PRESET=(`head -n 1 /usr/share/sonic/device/$PLATFORM/default_sku`)
+ HW_KEY=${PRESET[0]}
+ DEFAULT_PRESET=${PRESET[1]}
+
+ # Parse arguments passed
+ CONFIG_TYPE=$1
+ DEST_FILE=$2
+
+ if [ "$1" = "ztp" ]; then
+ /usr/lib/ztp/ztp-profile.sh create ${DEST_FILE}
+ elif [ "$1" = "factory" ]; then
+ rv=1
+
+ # Execute config initialization hooks
+ run_hookdir ${FACTORY_DEFAULT_HOOKS} ${CONFIG_SETUP_INITIALIZATION_FLAG}
+
+ # Use preset defined in default_sku
+ if [ ! -e ${DEST_FILE} ]; then
+ sonic-cfggen -H -k ${HW_KEY} --preset ${DEFAULT_PRESET} > ${DEST_FILE}
+ rv=$?
+ if [ $rv -ne 0 ]; then
+ return $rv
+ fi
+ fi
+ fi
+ return 0
+}
+
+# Create SONiC configuration for first time bootup
+# - If ZTP is enabled, ZTP configuraion is created
+# - If ZTP is disabled and updategraph is disabled, factory default configuration
+# is created
+# - If updategraph is enabled and ZTP is disabled, updategraph initializes
+# configuration
+do_config_initialization()
+{
+ if ! updategraph_is_enabled ; then
+ if ! ztp_is_enabled ; then
+ echo "No configuration detected, generating factory default configuration..."
+ generate_config factory ${CONFIG_DB_JSON}
+ load_config ${CONFIG_DB_JSON}
+ fi
+ fi
+
+ if ztp_is_enabled ; then
+ echo "No configuration detected, initiating zero touch provisioning..."
+ generate_config ztp ${TMP_ZTP_CONFIG_DB_JSON}
+ load_config ${TMP_ZTP_CONFIG_DB_JSON}
+ rm -f ${TMP_ZTP_CONFIG_DB_JSON}
+ fi
+
+ rm -f /tmp/pending_config_initialization
+}
+
+# Restore config-setup post migration hooks from a backup copy
+copy_post_migration_hooks()
+{
+ BACKUP_DIR=/etc/sonic/old_config/config-migration-post-hooks.d
+ if [ -d ${BACKUP_DIR} ]; then
+ [ -d ${CONFIG_POST_MIGRATION_HOOKS} ] || mkdir -p ${CONFIG_POST_MIGRATION_HOOKS}
+ for hook in $(ls -1 ${BACKUP_DIR}) ; do
+ if [ ! -e ${CONFIG_POST_MIGRATION_HOOKS}/$hook ]; then
+ cp -ar ${BACKUP_DIR}/$hook ${CONFIG_POST_MIGRATION_HOOKS}
+ fi
+ done
+ fi
+}
+
+# Perform configuration migration from backup copy.
+# - This step is performed when a new image is installed and SONiC switch boots into it
+do_config_migration()
+{
+ # Identify list of files to migrate
+ copy_list="minigraph.xml snmp.yml acl.json config_db.json frr"
+
+ # Migrate all configuration files from old to new
+ copy_config_files_and_directories $copy_list
+
+ # Migrate post-migration hooks
+ copy_post_migration_hooks
+
+ # Execute custom hooks if present
+ run_hookdir ${CONFIG_POST_MIGRATION_HOOKS} ${CONFIG_SETUP_POST_MIGRATION_FLAG}
+
+ if [ x"${WARM_BOOT}" == x"true" ]; then
+ echo "Warm reboot detected..."
+ disable_updategraph
+ rm -f /tmp/pending_config_migration
+ exit 0
+ elif [ -r ${CONFIG_DB_JSON} ]; then
+ echo "Use config_db.json from old system..."
+ sonic-cfggen -j ${CONFIG_DB_JSON} --write-to-db
+
+ if [[ -x /usr/bin/db_migrator.py ]]; then
+ # Migrate the DB to the latest schema version if needed
+ /usr/bin/db_migrator.py -o migrate
+ fi
+ elif [ -r ${MINGRAPH_FILE} ]; then
+ echo "Use minigraph.xml from old system..."
+ reload_minigraph
+ sonic-cfggen -d --print-data > ${CONFIG_DB_JSON}
+
+ # Disable updategraph
+ disable_updategraph
+ else
+ echo "Didn't found neither config_db.json nor minigraph.xml ..."
+ fi
+
+ rm -f /tmp/pending_config_migration
+}
+
+# Take a backup of current SONiC configuration
+do_config_backup()
+{
+ echo "Taking backup of curent configuration"
+ rm -rf /host/old_config
+ cp -ar /etc/sonic /host/old_config
+ [ -d ${CONFIG_POST_MIGRATION_HOOKS} ] && cp -arL ${CONFIG_POST_MIGRATION_HOOKS} /host/old_config
+
+ # Execute custom hooks if present
+ run_hookdir ${CONFIG_PRE_MIGRATION_HOOKS} ${CONFIG_SETUP_PRE_MIGRATION_FLAG}
+}
+
+# Process switch bootup event
+# - Check if it is warm boot and take no further action
+# - Perform configuration migration if requested
+# - Perform configuration initialization if requested
+# - If no saved SONiC configuration is found and ZTP is enabled,
+# start ZTP
+boot_config()
+{
+ check_system_warm_boot
+ if [ -e /tmp/pending_config_migration ] || [ -e ${CONFIG_SETUP_POST_MIGRATION_FLAG} ]; then
+ do_config_migration
+ fi
+
+ if [ -e /tmp/pending_config_initialization ] || [ -e ${CONFIG_SETUP_INITIALIZATION_FLAG} ]; then
+ do_config_initialization
+ fi
+
+ # If no startup configuration is found, create a configuration to be used
+ if [ ! -e ${CONFIG_DB_JSON} ]; then
+ do_config_initialization
+ # force ZTP to restart
+ if ztp_is_enabled ; then
+ ztp_status=$(ztp status -c)
+ if [ "$ztp_status" = "5:SUCCESS" ] || \
+ [ "$ztp_status" = "6:FAILED" ]; then
+ # Clear completed ztp information, before starting a new one
+ ztp erase -y
+ else
+ touch /tmp/pending_ztp_restart
+ fi
+ fi
+ fi
+}
+
+### Execution starts here ###
+
+CMD=$1
+# Default command is boot
+if [ "$CMD" = "" ] || [ "$CMD" = "help" ] || \
+ [ "$CMD" = "-h" ] || [ "$CMD" = "--help" ]; then
+ usage
+ exit 1
+fi
+
+# Process switch bootup event
+if [ "$CMD" = "boot" ]; then
+ boot_config
+fi
+
+# Process factory default configuration creation request
+if [ "$CMD" = "factory" ]; then
+ generate_config factory ${CONFIG_DB_JSON}
+fi
+
+# Take a backup of current configuration
+if [ "$CMD" = "backup" ]; then
+ do_config_backup
+fi
+
+exit 0
diff --git a/files/image_config/hostcfgd/hostcfgd b/files/image_config/hostcfgd/hostcfgd
index e10288c0dd37..4ac3be83d06e 100755
--- a/files/image_config/hostcfgd/hostcfgd
+++ b/files/image_config/hostcfgd/hostcfgd
@@ -2,7 +2,6 @@
# -*- coding: utf-8 -*-
import os
-import re
import sys
import subprocess
import syslog
@@ -24,13 +23,6 @@ TACPLUS_SERVER_TIMEOUT_DEFAULT = "5"
TACPLUS_SERVER_AUTH_TYPE_DEFAULT = "pap"
-def is_valid_hostname(hostname):
- if hostname[-1] == "." or len(hostname) > 253:
- return False
- allowed = re.compile("(?!-)[A-Z\d-]{1,63}(? /etc/network/interfaces
+# Check if ZTP DHCP policy has been installed
+if [ -e /etc/network/ifupdown2/policy.d/ztp_dhcp.json ]; then
+ # Obtain port operational state information
+ redis-dump -d 0 -k "PORT_TABLE:Ethernet*" -y > /tmp/ztp_port_data.json
+
+ if [ $? -ne 0 ] || [ ! -e /tmp/ztp_port_data.json ] || [ "$(cat /tmp/ztp_port_data.json)" = "" ]; then
+ echo "{}" > /tmp/ztp_port_data.json
+ fi
+
+ # Create an input file with ztp input information
+ echo "{ \"PORT_DATA\" : $(cat /tmp/ztp_port_data.json) }" > \
+ /tmp/ztp_input.json
+else
+ echo "{ \"ZTP_DHCP_DISABLED\" : \"true\" }" > /tmp/ztp_input.json
+fi
+
+# Create /e/n/i file for existing and active interfaces
+sonic-cfggen -d -j /tmp/ztp_input.json -t /usr/share/sonic/templates/interfaces.j2 > /etc/network/interfaces
[ -f /var/run/dhclient.eth0.pid ] && kill `cat /var/run/dhclient.eth0.pid` && rm -f /var/run/dhclient.eth0.pid
+[ -f /var/run/dhclient6.eth0.pid ] && kill `cat /var/run/dhclient6.eth0.pid` && rm -f /var/run/dhclient6.eth0.pid
+for intf_pid in $(ls -1 /var/run/dhclient*.Ethernet*.pid 2> /dev/null); do
+ [ -f ${intf_pid} ] && kill `cat ${intf_pid}` && rm -f ${intf_pid}
+done
+
+sonic-cfggen -d -j /tmp/ztp_input.json -t /usr/share/sonic/templates/90-dhcp6-systcl.conf.j2 > /etc/sysctl.d/90-dhcp6-systcl.conf
+# Read sysctl conf files again
+sysctl -p /etc/sysctl.d/90-dhcp6-systcl.conf
+
+sonic-cfggen -d -j /tmp/ztp_input.json -t /usr/share/sonic/templates/dhclient.conf.j2 > /etc/dhcp/dhclient.conf
systemctl restart networking
-ifdown lo && ifup lo
+# Clean-up created files
+rm -f /tmp/ztp_input.json /tmp/ztp_port_data.json
+
diff --git a/files/image_config/interfaces/interfaces.j2 b/files/image_config/interfaces/interfaces.j2
index 91be4437fc06..dbb2b1f3418a 100644
--- a/files/image_config/interfaces/interfaces.j2
+++ b/files/image_config/interfaces/interfaces.j2
@@ -5,28 +5,60 @@
# file: /etc/network/interfaces
#
{% endblock banner %}
+{% block mgmt_vrf %}
{% if (MGMT_VRF_CONFIG) and (MGMT_VRF_CONFIG['vrf_global']['mgmtVrfEnabled'] == "true") %}
auto mgmt
iface mgmt
vrf-table 5000
-{% endif %}
-{% block loopback %}
-# The loopback network interface
-auto lo
-iface lo inet loopback
-{% if (MGMT_VRF_CONFIG) and (MGMT_VRF_CONFIG['vrf_global']['mgmtVrfEnabled'] == "true") %}
# The loopback network interface for mgmt VRF that is required for applications like NTP
up ip link add lo-m type dummy
+ up ip link set dev lo-m master mgmt
up ip addr add 127.0.0.1/8 dev lo-m
up ip link set lo-m up
- up ip link set dev lo-m master mgmt
- down ip link delete dev lo-m
+ down ip link delete dev lo-m
{% endif %}
+{% endblock mgmt_vrf %}
+{% block loopback %}
+# The loopback network interface
+auto lo
+iface lo inet loopback
{% endblock loopback %}
{% block mgmt_interface %}
# The management network interface
auto eth0
+{% if (ZTP_DHCP_DISABLED is not defined) and (ZTP is defined) and (ZTP['mode'] is defined and ZTP['mode']['profile'] == 'active') %}
+
+
+# ZTP out-of-band interface
+allow-hotplug eth0
+{% if ZTP['mode']['ipv4'] == 'true' %}
+iface eth0 inet dhcp
+{% endif %}
+{% if ZTP['mode']['ipv6'] == 'true' %}
+iface eth0 inet6 dhcp
+ up sysctl net.ipv6.conf.eth0.accept_ra=1
+ down sysctl net.ipv6.conf.eth0.accept_ra=0
+{% endif %}
+
+{% if ZTP['mode']['inband'] == 'true' %}
+{% for port in PORT %}
+
+# ZTP in-band interface {{ port }}
+auto {{ port }}
+allow-hotplug {{ port }}
+{% if PORT_DATA['PORT_TABLE:'+port] is defined and PORT_DATA['PORT_TABLE:'+port]['value']['oper_status'] == 'up' %}
+{% if ZTP['mode']['ipv4'] == 'true' %}
+iface {{ port }} inet dhcp
+{% endif %}
+{% if ZTP['mode']['ipv6'] == 'true' %}
+iface {{ port }} inet6 dhcp
+{% endif %}
+{% endif %}
+{% endfor %}
+{% endif %}
+
+{% else %}
{% if MGMT_INTERFACE %}
{% for (name, prefix) in MGMT_INTERFACE|pfx_filter %}
iface eth0 {{ 'inet' if prefix | ipv4 else 'inet6' }} static
@@ -50,14 +82,14 @@ iface eth0 {{ 'inet' if prefix | ipv4 else 'inet6' }} static
up ip rule add to {{ route }} table {{ vrf_table }}
{% endfor %}
# management port down rules
- down ip {{ '-4' if prefix | ipv4 else '-6' }} route delete default via {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} dev eth0 table {{ vrf_table }}
- down ip {{ '-4' if prefix | ipv4 else '-6' }} route delete {{ prefix | network }}/{{ prefix | prefixlen }} dev eth0 table {{ vrf_table }}
- down ip {{ '-4' if prefix | ipv4 else '-6' }} rule delete from {{ prefix | ip }}/{{ '32' if prefix | ipv4 else '128' }} table {{ vrf_table }}
+ pre-down ip {{ '-4' if prefix | ipv4 else '-6' }} route delete default via {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} dev eth0 table {{ vrf_table }}
+ pre-down ip {{ '-4' if prefix | ipv4 else '-6' }} route delete {{ prefix | network }}/{{ prefix | prefixlen }} dev eth0 table {{ vrf_table }}
+ pre-down ip {{ '-4' if prefix | ipv4 else '-6' }} rule delete from {{ prefix | ip }}/{{ '32' if prefix | ipv4 else '128' }} table {{ vrf_table }}
{% if (MGMT_VRF_CONFIG) and (MGMT_VRF_CONFIG['vrf_global']['mgmtVrfEnabled'] == "true") %}
down cgdelete -g l3mdev:mgmt
{% endif %}
{% for route in MGMT_INTERFACE[(name, prefix)]['forced_mgmt_routes'] %}
- down ip rule delete to {{ route }} table {{ vrf_table }}
+ pre-down ip rule delete to {{ route }} table {{ vrf_table }}
{% endfor %}
{# TODO: COPP policy type rules #}
{% endfor %}
@@ -70,6 +102,10 @@ iface eth0 inet dhcp
up cgset -r l3mdev.master-device=mgmt mgmt
down cgdelete -g l3mdev:mgmt
{% endif %}
+iface eth0 inet6 dhcp
+ up sysctl net.ipv6.conf.eth0.accept_ra=1
+ down sysctl net.ipv6.conf.eth0.accept_ra=0
+{% endif %}
{% endif %}
#
source /etc/network/interfaces.d/*
diff --git a/files/image_config/kubernetes/kubernetes.list b/files/image_config/kubernetes/kubernetes.list
new file mode 100644
index 000000000000..5c888b830623
--- /dev/null
+++ b/files/image_config/kubernetes/kubernetes.list
@@ -0,0 +1,4 @@
+# The following is as recommended by https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
+# Whenever an OS update from Debian stretch is done, make sure to find the matching k8s sources list
+#
+deb https://apt.kubernetes.io/ kubernetes-xenial main
diff --git a/files/image_config/monit/conf.d/sonic-host b/files/image_config/monit/conf.d/sonic-host
index 8eaa1671d821..5a67f7a9909b 100644
--- a/files/image_config/monit/conf.d/sonic-host
+++ b/files/image_config/monit/conf.d/sonic-host
@@ -6,17 +6,17 @@
###############################################################################
check filesystem root-overlay with path /
- if space usage > 90% for 5 times within 10 cycles then alert
+ if space usage > 90% for 10 times within 20 cycles then alert
check filesystem var-log with path /var/log
- if space usage > 90% for 5 times within 10 cycles then alert
+ if space usage > 90% for 10 times within 20 cycles then alert
check system $HOST
- if memory usage > 90% for 5 times within 10 cycles then alert
- if cpu usage (user) > 90% for 5 times within 10 cycles then alert
- if cpu usage (system) > 90% for 5 times within 10 cycles then alert
+ if memory usage > 90% for 10 times within 20 cycles then alert
+ if cpu usage (user) > 90% for 10 times within 20 cycles then alert
+ if cpu usage (system) > 90% for 10 times within 20 cycles then alert
check process rsyslog with pidfile /var/run/rsyslogd.pid
start program = "/bin/systemctl start rsyslog.service"
stop program = "/bin/systemctl stop rsyslog.service"
- if totalmem > 800 MB for 5 times within 10 cycles then restart
+ if totalmem > 800 MB for 10 times within 20 cycles then restart
diff --git a/files/image_config/monit/monitrc b/files/image_config/monit/monitrc
index 7864069e3af1..74068f12d3f8 100644
--- a/files/image_config/monit/monitrc
+++ b/files/image_config/monit/monitrc
@@ -16,9 +16,10 @@
##
## Start Monit in the background (run as a daemon):
#
- set daemon 120 # check services at 2-minute intervals
-# with start delay 240 # optional: delay the first check by 4-minutes (by
-# # default Monit check immediately after Monit start)
+ set daemon 60 # check services at 1-minute intervals
+ with start delay 300 # we delay Monit to start monitoring for 5 minutes
+ # intentionally such that all containers and processes
+ # have ample time to start up.
#
#
## Set syslog logging. If you want to log to a standalone log file instead,
diff --git a/files/image_config/ntp/ntp.conf.j2 b/files/image_config/ntp/ntp.conf.j2
index cef6527fc28f..dbde694432e6 100644
--- a/files/image_config/ntp/ntp.conf.j2
+++ b/files/image_config/ntp/ntp.conf.j2
@@ -5,6 +5,10 @@
# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help
+# To avoid ntpd from panic and exit if the drift between new time and
+# current system time is large.
+tinker panic 0
+
driftfile /var/lib/ntp/ntp.drift
diff --git a/files/image_config/platform/rc.local b/files/image_config/platform/rc.local
index d64ec1bb7916..e36b20950b42 100755
--- a/files/image_config/platform/rc.local
+++ b/files/image_config/platform/rc.local
@@ -328,10 +328,10 @@ if [ -f $FIRST_BOOT_FILE ]; then
mv /host/grub.cfg /host/grub/grub.cfg
fi
+ # Create dir where following scripts put their output files
+ mkdir -p /var/platform
+
firsttime_exit
fi
-# Create dir where following scripts put their output files
-mkdir -p /var/platform
-
exit 0
diff --git a/files/image_config/procdockerstatsd/procdockerstatsd b/files/image_config/procdockerstatsd/procdockerstatsd
old mode 100644
new mode 100755
index 66d2d45009d5..65d4b029b0ff
--- a/files/image_config/procdockerstatsd/procdockerstatsd
+++ b/files/image_config/procdockerstatsd/procdockerstatsd
@@ -1,4 +1,4 @@
-# !/usr/bin/env python
+#!/usr/bin/env python
'''
procdockerstatsd
Daemon which periodically gathers process and docker statistics and pushes the data to STATE_DB
@@ -41,8 +41,8 @@ class ProcDockerStats:
def __init__(self):
self.state_db = swsssdk.SonicV2Connector(host=REDIS_HOSTIP)
- self.state_db.connect("STATE_DB")
-
+ self.state_db.connect("STATE_DB")
+
def run_command(self, cmd):
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
@@ -75,7 +75,7 @@ class ProcDockerStats:
# To remove extra space before UID
val = list(filter(None, values1))
# Merging extra columns created due to space in cmd ouput
- val[8:] = [''.join(val[8:])]
+ val[8:] = [' '.join(val[8:])]
process_data = dict(zip(keylist, val))
process_data_list.append(process_data)
return process_data_list
@@ -109,10 +109,10 @@ class ProcDockerStats:
for row in dict_list[0:]:
cid = row.get('CONTAINER ID')
if cid:
- key = 'DOCKER_STATS|' + str(cid)
+ key = 'DOCKER_STATS|' + str(cid)
dockerdict[key] = {}
dockerdict[key]['NAME'] = row.get('NAME')
-
+
splitcol = row.get('CPU %')
cpu = re.split("%", str(splitcol))
dockerdict[key]['CPU%'] = str(cpu[0])
@@ -131,7 +131,7 @@ class ProcDockerStats:
netio = re.split(" / ", str(splitcol))
dockerdict[key]['NET_IN_BYTES'] = str(self.convert_to_bytes(netio[0]))
dockerdict[key]['NET_OUT_BYTES'] = str(self.convert_to_bytes(netio[1]))
-
+
splitcol = row.get('BLOCK I/O')
blockio = re.split(" / ", str(splitcol))
dockerdict[key]['BLOCK_IN_BYTES'] = str(self.convert_to_bytes(blockio[0]))
diff --git a/files/image_config/procdockerstatsd/procdockerstatsd.service b/files/image_config/procdockerstatsd/procdockerstatsd.service
index 4e38c350a577..010dac15b2e6 100644
--- a/files/image_config/procdockerstatsd/procdockerstatsd.service
+++ b/files/image_config/procdockerstatsd/procdockerstatsd.service
@@ -6,7 +6,7 @@ After=database.service updategraph.service
[Service]
Type=simple
ExecStart=/usr/bin/procdockerstatsd
-Restart=Always
+Restart=always
[Install]
WantedBy=multi-user.target
diff --git a/files/image_config/process-reboot-cause/process-reboot-cause b/files/image_config/process-reboot-cause/process-reboot-cause
index e5d228b4c6b6..409deb7d6859 100755
--- a/files/image_config/process-reboot-cause/process-reboot-cause
+++ b/files/image_config/process-reboot-cause/process-reboot-cause
@@ -62,10 +62,10 @@ def parse_warmfast_reboot_from_proc_cmdline():
if os.path.isfile(REBOOT_TYPE_KEXEC_FILE):
with open(REBOOT_TYPE_KEXEC_FILE, "r") as cause_file:
cause_file_kexec = cause_file.readline()
- m = re.match(REBOOT_TYPE_KEXEC_PATTERN_WARM, cause_file_kexec)
+ m = re.search(REBOOT_TYPE_KEXEC_PATTERN_WARM, cause_file_kexec)
if m and m.group(1):
return 'warm-reboot'
- m = re.match(REBOOT_TYPE_KEXEC_PATTERN_FAST, cause_file_kexec)
+ m = re.search(REBOOT_TYPE_KEXEC_PATTERN_FAST, cause_file_kexec)
if m and m.group(1):
return 'fast-reboot'
return None
@@ -77,13 +77,61 @@ def find_software_reboot_cause():
if os.path.isfile(REBOOT_CAUSE_FILE):
with open(REBOOT_CAUSE_FILE, "r") as cause_file:
software_reboot_cause = cause_file.readline().rstrip('\n')
+ log_info("{} indicates the reboot cause: {}".format(REBOOT_CAUSE_FILE, software_reboot_cause))
+ else:
+ log_info("Reboot cause file {} not found".format(REBOOT_CAUSE_FILE))
if os.path.isfile(FIRST_BOOT_PLATFORM_FILE):
os.remove(FIRST_BOOT_PLATFORM_FILE)
return software_reboot_cause
+
+
+def find_proc_cmdline_reboot_cause():
+ proc_cmdline_reboot_cause = parse_warmfast_reboot_from_proc_cmdline()
+ if proc_cmdline_reboot_cause:
+ log_info("/proc/cmdline indicates reboot type: {}".format(proc_cmdline_reboot_cause))
+ else:
+ log_info("No reboot cause found from /proc/cmdline")
+ return proc_cmdline_reboot_cause
+
+
+def find_hardware_reboot_cause():
+ hardware_reboot_cause = None
+
+ # Until all platform vendors have provided sonic_platform packages,
+ # if there is no sonic_platform package installed, we only provide
+ # software-related reboot causes.
+ try:
+ import sonic_platform
+
+ platform = sonic_platform.platform.Platform()
+
+ chassis = platform.get_chassis()
+
+ hardware_reboot_cause_major, hardware_reboot_cause_minor = chassis.get_reboot_cause()
+
+ if hardware_reboot_cause_major == chassis.REBOOT_CAUSE_NON_HARDWARE:
+ # The reboot was not caused by hardware. If there is a REBOOT_CAUSE_FILE, it will
+ # contain any software-related reboot info. We will use it as the previous cause.
+ pass
+ elif hardware_reboot_cause_major == chassis.REBOOT_CAUSE_HARDWARE_OTHER:
+ hardware_reboot_cause = "{} ({})".format(hardware_reboot_cause_major, hardware_reboot_cause_minor)
+ else:
+ hardware_reboot_cause = hardware_reboot_cause_major
+ except ImportError as err:
+ log_warning("sonic_platform package not installed. Unable to detect hardware reboot causes.")
+
+ if hardware_reboot_cause:
+ log_info("Platform api indicates reboot cause {}".format(hardware_reboot_cause))
+ else:
+ log_info("No reboot cause found from platform api")
+
+ return hardware_reboot_cause
+
+
def main():
log_info("Starting up...")
@@ -99,54 +147,33 @@ def main():
if os.path.exists(PREVIOUS_REBOOT_CAUSE_FILE):
os.remove(PREVIOUS_REBOOT_CAUSE_FILE)
-
# Set a default previous reboot cause
previous_reboot_cause = UNKNOWN_REBOOT_CAUSE
- # Until all platform vendors have provided sonic_platform packages,
- # if there is no sonic_platform package installed, we only provide
- # software-related reboot causes.
- try:
- import sonic_platform
-
- # 1. Check if the previous reboot was warm/fast reboot by testing whether there is "fast|fastfast|warm" in /proc/cmdline
- # If yes, the content of /hosts/reboot-cause/reboot-cause.txt will be treated as the reboot cause
- proc_cmdline_reboot_cause = parse_warmfast_reboot_from_proc_cmdline()
- if proc_cmdline_reboot_cause:
- log_info("/proc/cmdline indicates reboot type: {}".format(proc_cmdline_reboot_cause))
- if os.path.isfile(REBOOT_CAUSE_FILE):
- with open(REBOOT_CAUSE_FILE, "r") as cause_file:
- proc_cmdline_reboot_cause = cause_file.readline().rstrip('\n')
- else:
- # /proc/cmdline says it's a warm/fast reboot but /host/reboot-cause.txt doesn't exist.
- # This could happen when upgrading from a version doesn't support reboot cause.
- log_info("Reboot cause file {} doesn't exist".format(REBOOT_CAUSE_DIR))
-
- if proc_cmdline_reboot_cause is not None:
- previous_reboot_cause = proc_cmdline_reboot_cause
- else:
- # 2. Check if the previous reboot was caused by hardware
- # If yes, the hardware reboot cause will be treated as the reboot cause
- platform = sonic_platform.platform.Platform()
-
- chassis = platform.get_chassis()
-
- hardware_reboot_cause, optional_details = chassis.get_reboot_cause()
-
- if hardware_reboot_cause == chassis.REBOOT_CAUSE_NON_HARDWARE:
- # The reboot was not caused by hardware. If there is a REBOOT_CAUSE_FILE, it will
- # contain any software-related reboot info. We will use it as the previous cause.
- previous_reboot_cause = find_software_reboot_cause()
- elif hardware_reboot_cause == chassis.REBOOT_CAUSE_HARDWARE_OTHER:
- previous_reboot_cause = "{} ({})".format(hardware_reboot_cause, optional_details)
- else:
- previous_reboot_cause = hardware_reboot_cause
- except ImportError as err:
- log_warning("sonic_platform package not installed. Unable to detect hardware reboot causes.")
-
- # If there is a REBOOT_CAUSE_FILE, it will contain any software-related
- # reboot info. We will use it as the previous cause.
- previous_reboot_cause = find_software_reboot_cause()
+ # 1. Check if the previous reboot was warm/fast reboot by testing whether there is "fast|fastfast|warm" in /proc/cmdline
+ proc_cmdline_reboot_cause = find_proc_cmdline_reboot_cause()
+
+ # 2. Check if the previous reboot was caused by hardware
+ # If yes, the hardware reboot cause will be treated as the reboot cause
+ hardware_reboot_cause = find_hardware_reboot_cause()
+
+ # 3. If there is a REBOOT_CAUSE_FILE, it will contain any software-related
+ # reboot info. We will use it as the previous cause.
+ software_reboot_cause = find_software_reboot_cause()
+
+ # The main decision logic of the reboot cause:
+ # If there is a reboot cause indicated by /proc/cmdline, it should be warmreboot/fastreboot
+ # the software_reboot_cause which is the content of /hosts/reboot-cause/reboot-cause.txt
+ # will be treated as the reboot cause
+ # Elif there is a reboot cause indicated by platform API,
+ # the hardware_reboot_cause will be treated as the reboot cause
+ # Else the software_reboot_cause will be treated as the reboot cause
+ if proc_cmdline_reboot_cause is not None:
+ previous_reboot_cause = software_reboot_cause
+ elif hardware_reboot_cause is not None:
+ previous_reboot_cause = hardware_reboot_cause
+ else:
+ previous_reboot_cause = software_reboot_cause
# Write the previous reboot cause to PREVIOUS_REBOOT_CAUSE_FILE
with open(PREVIOUS_REBOOT_CAUSE_FILE, "w") as prev_cause_file:
diff --git a/files/image_config/process-reboot-cause/process-reboot-cause.service b/files/image_config/process-reboot-cause/process-reboot-cause.service
index a429339dbe58..b9821f60c420 100644
--- a/files/image_config/process-reboot-cause/process-reboot-cause.service
+++ b/files/image_config/process-reboot-cause/process-reboot-cause.service
@@ -5,6 +5,3 @@ After=rc-local.service
[Service]
Type=simple
ExecStart=/usr/bin/process-reboot-cause
-
-[Install]
-WantedBy=multi-user.target
diff --git a/files/image_config/snmp/snmp.yml b/files/image_config/snmp/snmp.yml
index b200670f0d94..117619975fbb 100644
--- a/files/image_config/snmp/snmp.yml
+++ b/files/image_config/snmp/snmp.yml
@@ -1,5 +1,2 @@
snmp_rocommunity: public
snmp_location: public
-v1_trap_dest: NotConfigured
-v2_trap_dest: NotConfigured
-v3_trap_dest: NotConfigured
diff --git a/files/image_config/topology/topology.service b/files/image_config/topology/topology.service
new file mode 100644
index 000000000000..eea4bf65230a
--- /dev/null
+++ b/files/image_config/topology/topology.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=Internal topology service
+Requires=database.service
+After=database.service
+PartOf=database.service
+
+[Service]
+Type=oneshot
+User=root
+RemainAfterExit=yes
+ExecStart=/usr/bin/topology.sh start
+ExecStop=/usr/bin/topology.sh stop
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/files/image_config/topology/topology.sh b/files/image_config/topology/topology.sh
new file mode 100755
index 000000000000..dde7da247484
--- /dev/null
+++ b/files/image_config/topology/topology.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# This script is invoked by topology.service only
+# for multi-asic virtual platform. For multi-asic platform
+# multiple Database instances are present
+# and HWKSU information is retrieved from first database instance.
+#
+
+start() {
+ TOPOLOGY_SCRIPT="topology.sh"
+ PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`
+ HWSKU=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hwsku"]'`
+ /usr/share/sonic/device/$PLATFORM/$HWSKU/$TOPOLOGY_SCRIPT start
+}
+stop() {
+ TOPOLOGY_SCRIPT="topology.sh"
+ PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`
+ HWSKU=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hwsku"]'`
+ usr/share/sonic/device/$PLATFORM/$HWSKU/$TOPOLOGY_SCRIPT stop
+}
+
+case "$1" in
+ start|stop)
+ $1
+ ;;
+ *)
+ echo "Usage: $0 {start|stop}"
+ ;;
+esac
diff --git a/files/image_config/updategraph/updategraph b/files/image_config/updategraph/updategraph
index 2eb510afa4e1..a24d452b1ad2 100755
--- a/files/image_config/updategraph/updategraph
+++ b/files/image_config/updategraph/updategraph
@@ -1,16 +1,14 @@
#!/bin/bash
-CONFIG_DB_INDEX=4
-
reload_minigraph()
{
echo "Reloading minigraph..."
if [ ! -f /etc/sonic/init_cfg.json ]; then
echo "{}" > /etc/sonic/init_cfg.json
fi
- redis-cli -n $CONFIG_DB_INDEX FLUSHDB
+ sonic-db-cli CONFIG_DB FLUSHDB
sonic-cfggen -H -m -j /etc/sonic/init_cfg.json --write-to-db
- redis-cli -n $CONFIG_DB_INDEX SET "CONFIG_DB_INITIALIZED" "1"
+ sonic-db-cli CONFIG_DB SET "CONFIG_DB_INITIALIZED" "1"
if [ -f /etc/sonic/acl.json ]; then
acl-loader update full /etc/sonic/acl.json
fi
@@ -26,32 +24,6 @@ reload_minigraph()
fi
}
-function copy_config_files_and_directories()
-{
- for file_dir in $@; do
- if [ -f /etc/sonic/old_config/${file_dir} ] || [ -d /etc/sonic/old_config/${file_dir} ]; then
- logger "Copying SONiC configuration ${file_dir} ..."
- cp -ar /etc/sonic/old_config/${file_dir} /etc/sonic/
- else
- logger "Missing SONiC configuration ${file_dir} ..."
- fi
- done
-
- sync
-}
-
-function check_system_warm_boot()
-{
- SYSTEM_WARM_START=`/usr/bin/redis-cli -n 6 hget "WARM_RESTART_ENABLE_TABLE|system" enable`
- # SYSTEM_WARM_START could be empty, always make WARM_BOOT meaningful.
- if [[ x"$SYSTEM_WARM_START" == x"true" ]]; then
- WARM_BOOT="true"
- else
- WARM_BOOT="false"
- fi
-}
-
-
if [ ! -f /etc/sonic/updategraph.conf ]; then
echo "No updategraph.conf found, generating a default one."
echo "enabled=false" >/etc/sonic/updategraph.conf
@@ -59,46 +31,6 @@ fi
. /etc/sonic/updategraph.conf
-check_system_warm_boot
-copy_list="minigraph.xml snmp.yml acl.json config_db.json frr"
-if [ -f /tmp/pending_config_migration ]; then
- copy_config_files_and_directories $copy_list
- if [ x"${WARM_BOOT}" == x"true" ]; then
- echo "Warm reboot detected..."
- elif [ -r /etc/sonic/config_db.json ]; then
- echo "Use config_db.json from old system..."
- sonic-cfggen -j /etc/sonic/config_db.json --write-to-db
-
- if [[ -x /usr/bin/db_migrator.py ]]; then
- # Migrate the DB to the latest schema version if needed
- /usr/bin/db_migrator.py -o migrate
- fi
- elif [ -r /etc/sonic/minigraph.xml ]; then
- echo "Use minigraph.xml from old system..."
- reload_minigraph
- sonic-cfggen -d --print-data > /etc/sonic/config_db.json
- else
- echo "Didn't found neither config_db.json nor minigraph.xml ..."
- fi
- rm -f /tmp/pending_config_migration
- sed -i "/enabled=/d" /etc/sonic/updategraph.conf
- echo "enabled=false" >> /etc/sonic/updategraph.conf
- exit 0
-fi
-
-if [ -f /tmp/pending_config_initialization ]; then
- rm -f /tmp/pending_config_initialization
- if [ "$enabled" != "true" ]; then
- PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`
- PRESET=(`head -n 1 /usr/share/sonic/device/$PLATFORM/default_sku`)
- sonic-cfggen -H -k ${PRESET[0]} --preset ${PRESET[1]} > /etc/sonic/config_db.json
- redis-cli -n $CONFIG_DB_INDEX FLUSHDB
- sonic-cfggen -j /etc/sonic/config_db.json --write-to-db
- redis-cli -n $CONFIG_DB_INDEX SET "CONFIG_DB_INITIALIZED" "1"
- exit 0
- fi
-fi
-
if [ "$enabled" = "reload_only" ]; then
reload_minigraph
sed -i "/enabled=/d" /etc/sonic/updategraph.conf
@@ -111,6 +43,12 @@ if [ "$enabled" != "true" ]; then
exit 0
fi
+# If ZTP package is available and enabled, use ZTP to download and load the graph.
+if [ -e /usr/bin/ztp ] && [ "$(ztp status -c)" != "0:DISABLED" ]; then
+ echo "ZTP is available and enabled. Skipping graph update."
+ exit 0
+fi
+
ACL_URL=$acl_src
if [ "$src" = "dhcp" ]; then
@@ -137,9 +75,9 @@ if [ "$src" = "dhcp" ]; then
else
cp -f /tmp/device_meta.json /etc/sonic/config_db.json
fi
- redis-cli -n $CONFIG_DB_INDEX FLUSHDB
+ sonic-db-cli CONFIG_DB FLUSHDB
sonic-cfggen -j /etc/sonic/config_db.json --write-to-db
- redis-cli -n $CONFIG_DB_INDEX SET "CONFIG_DB_INITIALIZED" "1"
+ sonic-db-cli CONFIG_DB SET "CONFIG_DB_INITIALIZED" "1"
if [ "$dhcp_as_static" = "true" ]; then
sed -i "/enabled=/d" /etc/sonic/updategraph.conf
echo "enabled=false" >> /etc/sonic/updategraph.conf
diff --git a/files/image_config/warmboot-finalizer/finalize-warmboot.sh b/files/image_config/warmboot-finalizer/finalize-warmboot.sh
index 32c9c8444cc3..0f9e0f7da299 100755
--- a/files/image_config/warmboot-finalizer/finalize-warmboot.sh
+++ b/files/image_config/warmboot-finalizer/finalize-warmboot.sh
@@ -3,7 +3,7 @@
VERBOSE=no
# Check components
-COMP_LIST="orchagent neighsyncd bgp"
+COMP_LIST="orchagent neighsyncd bgp natsyncd"
EXP_STATE="reconciled"
ASSISTANT_SCRIPT="/usr/bin/neighbor_advertiser"
@@ -20,7 +20,7 @@ function debug()
function check_warm_boot()
{
- WARM_BOOT=`/usr/bin/redis-cli -n 6 hget "WARM_RESTART_ENABLE_TABLE|system" enable`
+ WARM_BOOT=`sonic-db-cli STATE_DB hget "WARM_RESTART_ENABLE_TABLE|system" enable`
}
@@ -29,12 +29,10 @@ function wait_for_database_service()
debug "Wait for database to become ready..."
# Wait for redis server start before database clean
- until [[ $(/usr/bin/docker exec database redis-cli ping | grep -c PONG) -gt 0 ]];
- do sleep 1;
- done
+ /usr/bin/docker exec database ping_pong_db_insts
# Wait for configDB initialization
- until [[ $(/usr/bin/docker exec database redis-cli -n 4 GET "CONFIG_DB_INITIALIZED") ]];
+ until [[ $(sonic-db-cli CONFIG_DB GET "CONFIG_DB_INITIALIZED") ]];
do sleep 1;
done
@@ -44,7 +42,7 @@ function wait_for_database_service()
function get_component_state()
{
- /usr/bin/redis-cli -n 6 hget "WARM_RESTART_TABLE|$1" state
+ sonic-db-cli STATE_DB hget "WARM_RESTART_TABLE|$1" state
}
diff --git a/files/initramfs-tools/arista-convertfs.j2 b/files/initramfs-tools/arista-convertfs.j2
index 535bb441f117..56616d2ba04a 100644
--- a/files/initramfs-tools/arista-convertfs.j2
+++ b/files/initramfs-tools/arista-convertfs.j2
@@ -18,6 +18,8 @@ flash_dev=''
block_flash=''
aboot_flag=''
backup_file=''
+prev_os=''
+sonic_fast_reboot=''
# Wait until get the fullpath of flash device, e.g., /dev/sda
wait_get_flash_dev() {
@@ -133,9 +135,11 @@ for x in "$@"; do
docker_inram=*)
docker_inram="${x#docker_inram=}"
;;
+ prev_os=*)
+ prev_os="${x#prev_os=}"
+ ;;
SONIC_BOOT_TYPE=warm*|SONIC_BOOT_TYPE=fast*)
- # Skip this script for warm-reboot and fast-reboot
- exit 0
+ sonic_fast_reboot=true
;;
esac
done
@@ -143,6 +147,9 @@ done
# Check aboot
[ -z "$aboot_flag" ] && exit 0
+# Skip this script for warm-reboot/fast-reboot from sonic
+[ "$sonic_fast_reboot" == true ] && [ "$prev_os" != eos ] && exit 0
+
# Get flash dev name
if [ -z "$block_flash" ]; then
echo "Error: flash device info is not provided"
diff --git a/files/initramfs-tools/union-mount.j2 b/files/initramfs-tools/union-mount.j2
index f6f1deff4220..39a514b0669e 100644
--- a/files/initramfs-tools/union-mount.j2
+++ b/files/initramfs-tools/union-mount.j2
@@ -21,6 +21,7 @@ set_tmpfs_log_partition_size()
[ X"$aboot_platform" = X"x86_64-arista_7050_qx32" ] && return
[ X"$aboot_platform" = X"x86_64-arista_7050_qx32s" ] && return
[ X"$aboot_platform" = X"x86_64-arista_7060_cx32s" ] && return
+ [ X"$aboot_platform" = X"x86_64-arista_7060cx2_32s" ] && return
# set varlogsize to existing var-log.ext4 size
if [ -f ${rootmnt}/host/disk-img/var-log.ext4 ]; then
diff --git a/files/scripts/arp_update b/files/scripts/arp_update
index 055aa98baf5d..3cc9cd267985 100755
--- a/files/scripts/arp_update
+++ b/files/scripts/arp_update
@@ -46,5 +46,28 @@ while /bin/true; do
ip6cmd="ip -6 neigh show | grep -v fe80 | grep $vlan | cut -d ' ' -f 1,3 | $ndisc6cmd"
eval `eval $ip6cmd`
done
+
+ # sleep here before handling the mismatch as it is not required during startup
sleep 300
+
+ # refresh neighbor entries from APP_DB in case of mismatch with kernel
+ DBNEIGH=$(sonic-db-cli APPL_DB keys NEIGH_TABLE*)
+ KERNEIGH4=$(ip -4 neigh show | grep Vlan | cut -d ' ' -f 1,3 --output-delimiter=',')
+ KERNEIGH6=$(ip -6 neigh show | grep -v fe80 | grep Vlan | cut -d ' ' -f 1,3 --output-delimiter=',')
+ for neigh in $DBNEIGH; do
+ intf="$( cut -d ':' -f 2 <<< "$neigh" )"
+ ip="$( cut -d ':' -f 3- <<< "$neigh" )"
+ if [[ $intf == *"Vlan"* ]]; then
+ if [[ $ip == *"."* ]] && [[ ! $KERNEIGH4 =~ "${ip},${intf}" ]]; then
+ pingcmd="timeout 0.2 ping -I $intf -n -q -i 0 -c 1 -W 1 $ip >/dev/null"
+ eval $pingcmd
+ logger "arp_update: mismatch arp entry, pinging ${ip} on ${intf}"
+ elif [[ $ip == *":"* ]] && [[ ! $KERNEIGH6 =~ "${ip},${intf}" ]]; then
+ ping6cmd="timeout 0.2 ping6 -I $intf -n -q -i 0 -c 1 -W 1 $ip >/dev/null"
+ eval $ping6cmd
+ logger "arp_update: mismatch v6 nbr entry, pinging ${ip} on ${intf}"
+ fi
+ fi
+ done
+
done
diff --git a/files/scripts/configdb-load.sh b/files/scripts/configdb-load.sh
index 5ba2e0e0bc7f..b1bf761371bf 100755
--- a/files/scripts/configdb-load.sh
+++ b/files/scripts/configdb-load.sh
@@ -5,9 +5,13 @@ until [[ $(redis-cli ping | grep -c PONG) -gt 0 ]]; do
sleep 1;
done
-# If there is a config db dump file, load it
+# If there is a config_db.json dump file, load it.
if [ -r /etc/sonic/config_db.json ]; then
- sonic-cfggen -j /etc/sonic/config_db.json --write-to-db
+ if [ -r /etc/sonic/init_cfg.json ]; then
+ sonic-cfggen -j /etc/sonic/init_cfg.json -j /etc/sonic/config_db.json --write-to-db
+ else
+ sonic-cfggen -j /etc/sonic/config_db.json --write-to-db
+ fi
fi
-redis-cli -n 4 SET "CONFIG_DB_INITIALIZED" "1"
+sonic-db-cli CONFIG_DB SET "CONFIG_DB_INITIALIZED" "1"
diff --git a/files/scripts/sonic-netns-exec b/files/scripts/sonic-netns-exec
new file mode 100755
index 000000000000..a0dfc6f9ab07
--- /dev/null
+++ b/files/scripts/sonic-netns-exec
@@ -0,0 +1,12 @@
+#!/bin/bash
+# Wrapper to execute any command in a specific
+# network namespace.
+# Usage:
+# sonic-netns-exec
+NS="$1"
+shift
+if [ ! -z "$NS" ]; then
+ ip netns exec $NS "$@"
+else
+ "$@"
+fi
diff --git a/files/scripts/supervisor-proc-exit-listener b/files/scripts/supervisor-proc-exit-listener
index 8d1735cd2b0c..cf154b3a5c10 100755
--- a/files/scripts/supervisor-proc-exit-listener
+++ b/files/scripts/supervisor-proc-exit-listener
@@ -1,17 +1,34 @@
#!/usr/bin/env python
+import getopt
import os
import signal
import sys
import syslog
+import swsssdk
+
from supervisor import childutils
# Contents of file should be the names of critical processes (as defined in
# supervisor.conf file), one per line
CRITICAL_PROCESSES_FILE = '/etc/supervisor/critical_processes'
-def main():
+# This table in databse contains the features for container and each
+# feature for a row will be configured a state or number.
+CONTAINER_FEATURE_TABLE_NAME = 'CONTAINER_FEATURE'
+
+def main(argv):
+ container_name = None
+ opts, args = getopt.getopt(argv, "c:", ["container-name="])
+ for opt, arg in opts:
+ if opt in ("-c", "--container-name"):
+ container_name = arg
+
+ if not container_name:
+ syslog.syslog(syslog.LOG_ERR, "Container name not specified. Exiting...")
+ sys.exit(1)
+
# Read the list of critical processes from a file
with open(CRITICAL_PROCESSES_FILE, 'r') as f:
critical_processes = [line.rstrip('\n') for line in f]
@@ -35,12 +52,33 @@ def main():
processname = payload_headers['processname']
groupname = payload_headers['groupname']
- # If a critical process exited unexpectedly, terminate supervisor
- if expected == 0 and processname in critical_processes or groupname in critical_processes:
+ # Read the status of auto-restart feature from Config_DB.
+ if container_name != 'database':
+ config_db = swsssdk.ConfigDBConnector()
+ config_db.connect()
+ container_features_table = config_db.get_table(CONTAINER_FEATURE_TABLE_NAME)
+ if not container_features_table:
+ syslog.syslog(syslog.LOG_ERR, "Unable to retrieve container features table from Config DB. Exiting...")
+ sys.exit(2)
+
+ if not container_features_table.has_key(container_name):
+ syslog.syslog(syslog.LOG_ERR, "Unable to retrieve features for container '{}'. Exiting...".format(container_name))
+ sys.exit(3)
+
+ restart_feature = container_features_table[container_name].get('auto_restart')
+ if not restart_feature:
+ syslog.syslog(syslog.LOG_ERR, "Unable to determine auto-restart feature status for container '{}'. Exiting...".format(container_name))
+ sys.exit(4)
+
+ # If container is database or auto-restart feature is enabled and at the same time
+ # a critical process exited unexpectedly, terminate supervisor
+ if ((container_name == 'database' or restart_feature == 'enabled') and expected == 0 and
+ (processname in critical_processes or groupname in critical_processes)):
MSG_FORMAT_STR = "Process {} exited unxepectedly. Terminating supervisor..."
msg = MSG_FORMAT_STR.format(payload_headers['processname'])
syslog.syslog(syslog.LOG_INFO, msg)
os.kill(os.getppid(), signal.SIGTERM)
+
if __name__ == "__main__":
- main()
+ main(sys.argv[1:])
diff --git a/files/scripts/swss.sh b/files/scripts/swss.sh
index 93f311019d66..360e331f3636 100755
--- a/files/scripts/swss.sh
+++ b/files/scripts/swss.sh
@@ -1,10 +1,7 @@
#!/bin/bash
-SERVICE="swss"
-PEER="syncd"
-DEPENDENT="teamd radv dhcp_relay"
-DEBUGLOG="/tmp/swss-syncd-debug.log"
-LOCKFILE="/tmp/swss-syncd-lock"
+DEPENDENT="radv dhcp_relay"
+MULTI_INST_DEPENDENT="teamd"
function debug()
{
@@ -14,25 +11,25 @@ function debug()
function lock_service_state_change()
{
- debug "Locking ${LOCKFILE} from ${SERVICE} service"
+ debug "Locking ${LOCKFILE} from ${SERVICE}$DEV service"
exec {LOCKFD}>${LOCKFILE}
/usr/bin/flock -x ${LOCKFD}
trap "/usr/bin/flock -u ${LOCKFD}" 0 2 3 15
- debug "Locked ${LOCKFILE} (${LOCKFD}) from ${SERVICE} service"
+ debug "Locked ${LOCKFILE} (${LOCKFD}) from ${SERVICE}$DEV service"
}
function unlock_service_state_change()
{
- debug "Unlocking ${LOCKFILE} (${LOCKFD}) from ${SERVICE} service"
+ debug "Unlocking ${LOCKFILE} (${LOCKFD}) from ${SERVICE}$DEV service"
/usr/bin/flock -u ${LOCKFD}
}
function check_warm_boot()
{
- SYSTEM_WARM_START=`/usr/bin/redis-cli -n 6 hget "WARM_RESTART_ENABLE_TABLE|system" enable`
- SERVICE_WARM_START=`/usr/bin/redis-cli -n 6 hget "WARM_RESTART_ENABLE_TABLE|${SERVICE}" enable`
+ SYSTEM_WARM_START=`sonic-netns-exec "$NET_NS" sonic-db-cli STATE_DB hget "WARM_RESTART_ENABLE_TABLE|system" enable`
+ SERVICE_WARM_START=`sonic-netns-exec "$NET_NS" sonic-db-cli STATE_DB hget "WARM_RESTART_ENABLE_TABLE|${SERVICE}" enable`
if [[ x"$SYSTEM_WARM_START" == x"true" ]] || [[ x"$SERVICE_WARM_START" == x"true" ]]; then
WARM_BOOT="true"
else
@@ -43,7 +40,7 @@ function check_warm_boot()
function validate_restore_count()
{
if [[ x"$WARM_BOOT" == x"true" ]]; then
- RESTORE_COUNT=`/usr/bin/redis-cli -n 6 hget "WARM_RESTART_TABLE|orchagent" restore_count`
+ RESTORE_COUNT=`sonic-netns-exec "$NET_NS" sonic-db-cli STATE_DB hget "WARM_RESTART_TABLE|orchagent" restore_count`
# We have to make sure db data has not been flushed.
if [[ -z "$RESTORE_COUNT" ]]; then
WARM_BOOT="false"
@@ -54,12 +51,10 @@ function validate_restore_count()
function wait_for_database_service()
{
# Wait for redis server start before database clean
- until [[ $(/usr/bin/docker exec database redis-cli ping | grep -c PONG) -gt 0 ]];
- do sleep 1;
- done
+ /usr/bin/docker exec database$DEV ping_pong_db_insts
# Wait for configDB initialization
- until [[ $(/usr/bin/docker exec database redis-cli -n 4 GET "CONFIG_DB_INITIALIZED") ]];
+ until [[ $(sonic-netns-exec "$NET_NS" sonic-db-cli CONFIG_DB GET "CONFIG_DB_INITIALIZED") ]];
do sleep 1;
done
}
@@ -69,7 +64,7 @@ function wait_for_database_service()
# $2 the string of a list of table prefixes
function clean_up_tables()
{
- redis-cli -n $1 EVAL "
+ sonic-netns-exec "$NET_NS" sonic-db-cli $1 EVAL "
local tables = {$2}
for i = 1, table.getn(tables) do
local matches = redis.call('KEYS', tables[i])
@@ -83,25 +78,48 @@ start_peer_and_dependent_services() {
check_warm_boot
if [[ x"$WARM_BOOT" != x"true" ]]; then
- /bin/systemctl start ${PEER}
+ if [[ ! -z $DEV ]]; then
+ /bin/systemctl start ${PEER}@$DEV
+ else
+ /bin/systemctl start ${PEER}
+ fi
for dep in ${DEPENDENT}; do
/bin/systemctl start ${dep}
done
+ for dep in ${MULTI_INST_DEPENDENT}; do
+ if [[ ! -z $DEV ]]; then
+ /bin/systemctl start ${dep}@$DEV
+ else
+ /bin/systemctl start ${dep}
+ fi
+ done
fi
}
stop_peer_and_dependent_services() {
# if warm start enabled or peer lock exists, don't stop peer service docker
if [[ x"$WARM_BOOT" != x"true" ]]; then
- /bin/systemctl stop ${PEER}
+ if [[ ! -z $DEV ]]; then
+ /bin/systemctl stop ${PEER}@$DEV
+ else
+ /bin/systemctl stop ${PEER}
+ fi
for dep in ${DEPENDENT}; do
/bin/systemctl stop ${dep}
done
+ for dep in ${MULTI_INST_DEPENDENT}; do
+ if [[ ! -z $DEV ]]; then
+ /bin/systemctl stop ${dep}@$DEV
+ else
+ /bin/systemctl stop ${dep}
+ fi
+ done
+
fi
}
start() {
- debug "Starting ${SERVICE} service..."
+ debug "Starting ${SERVICE}$DEV service..."
lock_service_state_change
@@ -109,21 +127,21 @@ start() {
check_warm_boot
validate_restore_count
- debug "Warm boot flag: ${SERVICE} ${WARM_BOOT}."
+ debug "Warm boot flag: ${SERVICE}$DEV ${WARM_BOOT}."
# Don't flush DB during warm boot
if [[ x"$WARM_BOOT" != x"true" ]]; then
debug "Flushing APP, ASIC, COUNTER, CONFIG, and partial STATE databases ..."
- /usr/bin/docker exec database redis-cli -n 0 FLUSHDB
- /usr/bin/docker exec database redis-cli -n 1 FLUSHDB
- /usr/bin/docker exec database redis-cli -n 2 FLUSHDB
- /usr/bin/docker exec database redis-cli -n 5 FLUSHDB
- clean_up_tables 6 "'PORT_TABLE*', 'MGMT_PORT_TABLE*', 'VLAN_TABLE*', 'VLAN_MEMBER_TABLE*', 'LAG_TABLE*', 'LAG_MEMBER_TABLE*', 'INTERFACE_TABLE*', 'MIRROR_SESSION*', 'VRF_TABLE*', 'FDB_TABLE*'"
+ sonic-netns-exec "$NET_NS" sonic-db-cli APPL_DB FLUSHDB
+ sonic-netns-exec "$NET_NS" sonic-db-cli ASIC_DB FLUSHDB
+ sonic-netns-exec "$NET_NS" sonic-db-cli COUNTERS_DB FLUSHDB
+ sonic-netns-exec "$NET_NS" sonic-db-cli FLEX_COUNTER_DB FLUSHDB
+ clean_up_tables STATE_DB "'PORT_TABLE*', 'MGMT_PORT_TABLE*', 'VLAN_TABLE*', 'VLAN_MEMBER_TABLE*', 'LAG_TABLE*', 'LAG_MEMBER_TABLE*', 'INTERFACE_TABLE*', 'MIRROR_SESSION*', 'VRF_TABLE*', 'FDB_TABLE*'"
fi
# start service docker
- /usr/bin/${SERVICE}.sh start
- debug "Started ${SERVICE} service..."
+ /usr/bin/${SERVICE}.sh start $DEV
+ debug "Started ${SERVICE}$DEV service..."
# Unlock has to happen before reaching out to peer service
unlock_service_state_change
@@ -136,7 +154,11 @@ wait() {
# NOTE: This assumes Docker containers share the same names as their
# corresponding services
for SECS in {1..60}; do
- RUNNING=$(docker inspect -f '{{.State.Running}}' ${PEER})
+ if [[ ! -z $DEV ]]; then
+ RUNNING=$(docker inspect -f '{{.State.Running}}' ${PEER}$DEV)
+ else
+ RUNNING=$(docker inspect -f '{{.State.Running}}' ${PEER})
+ fi
if [[ x"$RUNNING" == x"true" ]]; then
break
else
@@ -146,27 +168,31 @@ wait() {
# NOTE: This assumes Docker containers share the same names as their
# corresponding services
- /usr/bin/docker-wait-any ${SERVICE} ${PEER}
+ if [[ ! -z $DEV ]]; then
+ /usr/bin/docker-wait-any ${SERVICE}$DEV ${PEER}$DEV
+ else
+ /usr/bin/docker-wait-any ${SERVICE} ${PEER}
+ fi
}
stop() {
- debug "Stopping ${SERVICE} service..."
+ debug "Stopping ${SERVICE}$DEV service..."
[[ -f ${LOCKFILE} ]] || /usr/bin/touch ${LOCKFILE}
lock_service_state_change
check_warm_boot
- debug "Warm boot flag: ${SERVICE} ${WARM_BOOT}."
+ debug "Warm boot flag: ${SERVICE}$DEV ${WARM_BOOT}."
- /usr/bin/${SERVICE}.sh stop
- debug "Stopped ${SERVICE} service..."
+ /usr/bin/${SERVICE}.sh stop $DEV
+ debug "Stopped ${SERVICE}$DEV service..."
# Flush FAST_REBOOT table when swss needs to stop. The only
# time when this would take effect is when fast-reboot
# encountered error, e.g. syncd crashed. And swss needs to
# be restarted.
debug "Clearing FAST_REBOOT flag..."
- clean_up_tables 6 "'FAST_REBOOT*'"
+ clean_up_tables STATE_DB "'FAST_REBOOT*'"
# Unlock has to happen before reaching out to peer service
unlock_service_state_change
@@ -174,6 +200,18 @@ stop() {
stop_peer_and_dependent_services
}
+DEV=$2
+
+SERVICE="swss"
+PEER="syncd"
+DEBUGLOG="/tmp/swss-syncd-debug$DEV.log"
+LOCKFILE="/tmp/swss-syncd-lock$DEV"
+if [ "$DEV" ]; then
+ NET_NS="asic$DEV" #name of the network namespace
+else
+ NET_NS=""
+fi
+
case "$1" in
start|wait|stop)
$1
diff --git a/files/scripts/syncd.sh b/files/scripts/syncd.sh
index 05e5552a64b1..9847cfec9406 100755
--- a/files/scripts/syncd.sh
+++ b/files/scripts/syncd.sh
@@ -1,9 +1,5 @@
#!/bin/bash
-SERVICE="syncd"
-PEER="swss"
-DEBUGLOG="/tmp/swss-syncd-debug.log"
-LOCKFILE="/tmp/swss-syncd-lock"
function debug()
{
@@ -13,25 +9,25 @@ function debug()
function lock_service_state_change()
{
- debug "Locking ${LOCKFILE} from ${SERVICE} service"
+ debug "Locking ${LOCKFILE} from ${SERVICE}$DEV service"
exec {LOCKFD}>${LOCKFILE}
/usr/bin/flock -x ${LOCKFD}
trap "/usr/bin/flock -u ${LOCKFD}" 0 2 3 15
- debug "Locked ${LOCKFILE} (${LOCKFD}) from ${SERVICE} service"
+ debug "Locked ${LOCKFILE} (${LOCKFD}) from ${SERVICE}$DEV service"
}
function unlock_service_state_change()
{
- debug "Unlocking ${LOCKFILE} (${LOCKFD}) from ${SERVICE} service"
+ debug "Unlocking ${LOCKFILE} (${LOCKFD}) from ${SERVICE}$DEV service"
/usr/bin/flock -u ${LOCKFD}
}
function check_warm_boot()
{
- SYSTEM_WARM_START=`/usr/bin/redis-cli -n 6 hget "WARM_RESTART_ENABLE_TABLE|system" enable`
- SERVICE_WARM_START=`/usr/bin/redis-cli -n 6 hget "WARM_RESTART_ENABLE_TABLE|${SERVICE}" enable`
+ SYSTEM_WARM_START=`sonic-netns-exec "$NET_NS" sonic-db-cli STATE_DB hget "WARM_RESTART_ENABLE_TABLE|system" enable`
+ SERVICE_WARM_START=`sonic-netns-exec "$NET_NS" sonic-db-cli STATE_DB hget "WARM_RESTART_ENABLE_TABLE|${SERVICE}" enable`
# SYSTEM_WARM_START could be empty, always make WARM_BOOT meaningful.
if [[ x"$SYSTEM_WARM_START" == x"true" ]] || [[ x"$SERVICE_WARM_START" == x"true" ]]; then
WARM_BOOT="true"
@@ -43,12 +39,10 @@ function check_warm_boot()
function wait_for_database_service()
{
# Wait for redis server start before database clean
- until [[ $(/usr/bin/docker exec database redis-cli ping | grep -c PONG) -gt 0 ]];
- do sleep 1;
- done
+ /usr/bin/docker exec database$DEV ping_pong_db_insts
# Wait for configDB initialization
- until [[ $(/usr/bin/docker exec database redis-cli -n 4 GET "CONFIG_DB_INITIALIZED") ]];
+ until [[ $(sonic-netns-exec "$NET_NS" sonic-db-cli CONFIG_DB GET "CONFIG_DB_INITIALIZED") ]];
do sleep 1;
done
}
@@ -65,7 +59,7 @@ function getBootType()
;;
*SONIC_BOOT_TYPE=fast*|*fast-reboot*)
# check that the key exists
- if [[ $(redis-cli -n 6 GET "FAST_REBOOT|system") == "1" ]]; then
+ if [[ $(sonic-netns-exec "$NET_NS" sonic-db-cli STATE_DB GET "FAST_REBOOT|system") == "1" ]]; then
TYPE='fast'
else
TYPE='cold'
@@ -78,7 +72,7 @@ function getBootType()
}
start() {
- debug "Starting ${SERVICE} service..."
+ debug "Starting ${SERVICE}$DEV service..."
lock_service_state_change
@@ -87,7 +81,7 @@ start() {
wait_for_database_service
check_warm_boot
- debug "Warm boot flag: ${SERVICE} ${WARM_BOOT}."
+ debug "Warm boot flag: ${SERVICE}$DEV ${WARM_BOOT}."
if [[ x"$WARM_BOOT" == x"true" ]]; then
# Leave a mark for syncd scripts running inside docker.
@@ -129,7 +123,7 @@ start() {
fi
# start service docker
- /usr/bin/${SERVICE}.sh start
+ /usr/bin/${SERVICE}.sh start $DEV
debug "Started ${SERVICE} service..."
unlock_service_state_change
@@ -141,15 +135,15 @@ wait() {
/bin/systemctl start pmon
debug "Started pmon service"
fi
- /usr/bin/${SERVICE}.sh wait
+ /usr/bin/${SERVICE}.sh wait $DEV
}
stop() {
- debug "Stopping ${SERVICE} service..."
+ debug "Stopping ${SERVICE}$DEV service..."
lock_service_state_change
check_warm_boot
- debug "Warm boot flag: ${SERVICE} ${WARM_BOOT}."
+ debug "Warm boot flag: ${SERVICE}$DEV ${WARM_BOOT}."
if [[ x"$WARM_BOOT" == x"true" ]]; then
TYPE=warm
@@ -165,19 +159,19 @@ stop() {
if [[ x$sonic_asic_platform != x"mellanox" ]] || [[ x$TYPE != x"cold" ]]; then
debug "${TYPE} shutdown syncd process ..."
- /usr/bin/docker exec -i syncd /usr/bin/syncd_request_shutdown --${TYPE}
+ /usr/bin/docker exec -i syncd$DEV /usr/bin/syncd_request_shutdown --${TYPE}
# wait until syncd quits gracefully
- while docker top syncd | grep -q /usr/bin/syncd; do
+ while docker top syncd$DEV | grep -q /usr/bin/syncd; do
sleep 0.1
done
- /usr/bin/docker exec -i syncd /bin/sync
+ /usr/bin/docker exec -i syncd$DEV /bin/sync
debug "Finished ${TYPE} shutdown syncd process ..."
fi
- /usr/bin/${SERVICE}.sh stop
- debug "Stopped ${SERVICE} service..."
+ /usr/bin/${SERVICE}.sh stop $DEV
+ debug "Stopped ${SERVICE}$DEV service..."
# platform specific tasks
@@ -194,6 +188,19 @@ stop() {
unlock_service_state_change
}
+OP=$1
+DEV=$2
+
+SERVICE="syncd"
+PEER="swss"
+DEBUGLOG="/tmp/swss-syncd-debug$DEV.log"
+LOCKFILE="/tmp/swss-syncd-lock$DEV"
+if [ "$DEV" ]; then
+ NET_NS="asic$DEV" #name of the network namespace
+else
+ NET_NS=""
+fi
+
case "$1" in
start|wait|stop)
$1
diff --git a/installer/x86_64/install.sh b/installer/x86_64/install.sh
index 2cd579e28b29..6a347c78db73 100755
--- a/installer/x86_64/install.sh
+++ b/installer/x86_64/install.sh
@@ -555,15 +555,21 @@ EOF
# Add the logic to support grub-reboot and grub-set-default
cat <> $grub_cfg
if [ -s \$prefix/grubenv ]; then
- load_env
+ load_env
fi
-if [ "\${saved_entry}" ] ; then
- set default="\${saved_entry}"
+if [ "\${saved_entry}" ]; then
+ set default="\${saved_entry}"
fi
-if [ "\${next_entry}" ] ; then
- set default="\${next_entry}"
- set next_entry=
- save_env next_entry
+if [ "\${next_entry}" ]; then
+ set default="\${next_entry}"
+ unset next_entry
+ save_env next_entry
+fi
+if [ "\${onie_entry}" ]; then
+ set next_entry="\${default}"
+ set default="\${onie_entry}"
+ unset onie_entry
+ save_env onie_entry next_entry
fi
EOF
@@ -577,19 +583,22 @@ EOF
$onie_root_dir/tools/bin/onie-boot-mode -q -o install
fi
-# Add a menu entry for the DEMO OS
+# Add a menu entry for the SONiC OS
# Note: assume that apparmor is supported in the kernel
demo_grub_entry="$demo_volume_revision_label"
if [ "$install_env" = "sonic" ]; then
old_sonic_menuentry=$(cat /host/grub/grub.cfg | sed "/$running_sonic_revision/,/}/!d")
- demo_dev=$(echo $old_sonic_menuentry | sed -e "s/.*root\=\(.*\)rw.*/\1/")
+ grub_cfg_root=$(echo $old_sonic_menuentry | sed -e "s/.*root\=\(.*\)rw.*/\1/")
onie_menuentry=$(cat /host/grub/grub.cfg | sed "/menuentry ONIE/,/}/!d")
-fi
-
-if [ "$install_env" = "build" ]; then
+elif [ "$install_env" = "build" ]; then
grub_cfg_root=%%SONIC_ROOT%%
-else
- grub_cfg_root=$demo_dev
+else # install_env = "onie"
+ uuid=$(blkid "$demo_dev" | sed -ne 's/.* UUID=\"\([^"]*\)\".*/\1/p')
+ if [ -z "$uuid" ]; then
+ grub_cfg_root=$demo_dev
+ else
+ grub_cfg_root=UUID=$uuid
+ fi
fi
cat <> $grub_cfg
@@ -600,12 +609,12 @@ menuentry '$demo_grub_entry' {
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_msdos
insmod ext2
- linux /$image_dir/boot/vmlinuz-4.9.0-9-2-amd64 root=$grub_cfg_root rw $GRUB_CMDLINE_LINUX \
+ linux /$image_dir/boot/vmlinuz-4.9.0-11-2-amd64 root=$grub_cfg_root rw $GRUB_CMDLINE_LINUX \
net.ifnames=0 biosdevname=0 \
loop=$image_dir/$FILESYSTEM_SQUASHFS loopfstype=squashfs \
apparmor=1 security=apparmor varlog_size=$VAR_LOG_SIZE usbcore.autosuspend=-1 $ONIE_PLATFORM_EXTRA_CMDLINE_LINUX
echo 'Loading $demo_volume_label $demo_type initial ramdisk ...'
- initrd /$image_dir/boot/initrd.img-4.9.0-9-2-amd64
+ initrd /$image_dir/boot/initrd.img-4.9.0-11-2-amd64
}
EOF
diff --git a/platform/barefoot/bfn-modules/debian/control b/platform/barefoot/bfn-modules/debian/control
index c9a53ec1d08b..d6f7a991107d 100644
--- a/platform/barefoot/bfn-modules/debian/control
+++ b/platform/barefoot/bfn-modules/debian/control
@@ -7,6 +7,6 @@ Standards-Version: 3.9.3
Package: bfn-modules
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for bfn asic for mmap
diff --git a/platform/barefoot/bfn-modules/modules/bf_ioctl.h b/platform/barefoot/bfn-modules/modules/bf_ioctl.h
index e14716f50fa3..0644feb7c8c1 100644
--- a/platform/barefoot/bfn-modules/modules/bf_ioctl.h
+++ b/platform/barefoot/bfn-modules/modules/bf_ioctl.h
@@ -1,25 +1,28 @@
/*******************************************************************************
- * BAREFOOT NETWORKS CONFIDENTIAL & PROPRIETARY
- *
- * Copyright (c) 2018-2018 Barefoot Networks, Inc.
- *
- * NOTICE: All information contained herein is, and remains the property of
- * Barefoot Networks, Inc. and its suppliers, if any. The intellectual and
- * technical concepts contained herein are proprietary to Barefoot Networks,
- * Inc.
- * and its suppliers and may be covered by U.S. and Foreign Patents, patents in
- * process, and are protected by trade secret or copyright law.
- * Dissemination of this information or reproduction of this material is
- * strictly forbidden unless prior written permission is obtained from
- * Barefoot Networks, Inc.
- *
- * No warranty, explicit or implicit is provided, unless granted under a
- * written agreement with Barefoot Networks, Inc.
- *
- * $Id: $
- *
- ******************************************************************************/
+ Barefoot Networks Switch ASIC Linux driver
+ Copyright(c) 2015 - 2019 Barefoot Networks, Inc.
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ info@barefootnetworks.com
+ Barefoot Networks, 4750 Patrick Henry Drive, Santa Clara CA 95054
+
+*******************************************************************************/
#ifndef _BF_IOCTL_H_
#define _BF_IOCTL_H_
@@ -35,15 +38,35 @@ typedef uint64_t phys_addr_t;
#endif /* __KERNEL__ */
#define BF_IOC_MAGIC 'b'
+#define BF_TBUS_MSIX_INDICES_MAX 3
-typedef struct bf_dma_bus_map_s
+typedef struct bf_dma_bus_map_s
{
phys_addr_t phy_addr;
void *dma_addr;
size_t size;
} bf_dma_bus_map_t;
+typedef struct bf_tbus_msix_indices_s
+{
+ int cnt;
+ int indices[BF_TBUS_MSIX_INDICES_MAX];
+} bf_tbus_msix_indices_t;
+
+enum bf_intr_mode {
+ BF_INTR_MODE_NONE = 0,
+ BF_INTR_MODE_LEGACY,
+ BF_INTR_MODE_MSI,
+ BF_INTR_MODE_MSIX,
+};
+
+typedef struct bf_intr_mode_s {
+ enum bf_intr_mode intr_mode;
+} bf_intr_mode_t;
+
#define BF_IOCMAPDMAADDR _IOWR(BF_IOC_MAGIC, 0, bf_dma_bus_map_t)
-#define BF_IOCUNMAPDMAADDR _IOW(BF_IOC_MAGIC, 0, bf_dma_bus_map_t)
+#define BF_IOCUNMAPDMAADDR _IOW(BF_IOC_MAGIC, 1, bf_dma_bus_map_t)
+#define BF_TBUS_MSIX_INDEX _IOW(BF_IOC_MAGIC, 2, bf_tbus_msix_indices_t)
+#define BF_GET_INTR_MODE _IOR(BF_IOC_MAGIC, 3, bf_intr_mode_t)
#endif /* _BF_IOCTL_H_ */
diff --git a/platform/barefoot/bfn-modules/modules/bf_kdrv.c b/platform/barefoot/bfn-modules/modules/bf_kdrv.c
index a9e8e65f968b..d4c786c56b75 100644
--- a/platform/barefoot/bfn-modules/modules/bf_kdrv.c
+++ b/platform/barefoot/bfn-modules/modules/bf_kdrv.c
@@ -1,49 +1,31 @@
/*******************************************************************************
- * BAREFOOT NETWORKS CONFIDENTIAL & PROPRIETARY
- *
- * Copyright (c) 2015-2016 Barefoot Networks, Inc.
+ Barefoot Networks Switch ASIC Linux driver
+ Copyright(c) 2015 - 2019 Barefoot Networks, Inc.
- * All Rights Reserved.
- *
- * NOTICE: All information contained herein is, and remains the property of
- * Barefoot Networks, Inc. and its suppliers, if any. The intellectual and
- * technical concepts contained herein are proprietary to Barefoot Networks,
- * Inc.
- * and its suppliers and may be covered by U.S. and Foreign Patents, patents in
- * process, and are protected by trade secret or copyright law.
- * Dissemination of this information or reproduction of this material is
- * strictly forbidden unless prior written permission is obtained from
- * Barefoot Networks, Inc.
- *
- * No warranty, explicit or implicit is provided, unless granted under a
- * written agreement with Barefoot Networks, Inc.
- *
- * $Id: $
- *
- ******************************************************************************/
-/**
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2015 Barefoot Networks. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the...
- *
- **/
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ info@barefootnetworks.com
+ Barefoot Networks, 4750 Patrick Henry Drive, Santa Clara CA 95054
+
+*******************************************************************************/
/* bf_drv kernel module
*
- * This is kernel mode driver for Tofino chip.
+ * This is kernel mode driver for Tofino chip.
* Provides user space mmap service and user space "wait for interrupt"
* and "enable interrupt" services.
*/
@@ -52,21 +34,18 @@
#include
#include
#include
-#include
#include
-#include
-#include
#include
#include
#include
#include "bf_ioctl.h"
+#include "bf_kdrv.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
#include
#else
- #include
+ #include
#endif
-
#include
#include
#include
@@ -75,104 +54,26 @@
//#error unsupported linux kernel version
#endif
-/* TBD: Need to build with CONFIG_PCI_MSI */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
-extern int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec);
-extern int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec);
-#else
-extern int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec);
-extern int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, int maxvec);
-#endif
-
-#define PCI_VENDOR_ID_BF 0x1d1c
-#define TOFINO_DEV_ID_A0 0x01
-#define TOFINO_DEV_ID_B0 0x10
-#define TOFINO2_DEV_ID_A0 0x0100
-
-#ifndef PCI_MSIX_ENTRY_SIZE
-#define PCI_MSIX_ENTRY_SIZE 16
-#define PCI_MSIX_ENTRY_LOWER_ADDR 0
-#define PCI_MSIX_ENTRY_UPPER_ADDR 4
-#define PCI_MSIX_ENTRY_DATA 8
-#define PCI_MSIX_ENTRY_VECTOR_CTRL 12
-#define PCI_MSIX_ENTRY_CTRL_MASKBIT 1
+#ifdef BF_INCLUDE_KPKT
+/* kernel pkt driver entry/exit APIs */
+extern int bf_kpkt_init(struct pci_dev *pdev,
+ u8 *bar0_vaddr,
+ void **adapter_ptr,
+ int dev_id,
+ int pci_use_highmem,
+ unsigned long head_room,
+ int kpkt_dr_int_en,
+ unsigned long rx_desc_countp);
+extern void bf_kpkt_remove(void *adapter_ptr);
+extern void bf_kpkt_irqhandler(int irq, void *adapter_ptr);
+extern void bf_kpkt_set_pci_error(void *adapter_ptr, u8 pci_error);
#endif
-#define BF_CLASS_NAME "bf"
-#define BF_MAX_DEVICE_CNT 256
-#define BF_INTR_MODE_NONE_NAME "none"
-#define BF_INTR_MODE_LEGACY_NAME "legacy"
-#define BF_INTR_MODE_MSI_NAME "msi"
-#define BF_INTR_MODE_MSIX_NAME "msix"
-#define BF_MAX_BAR_MAPS 6
-#define BF_MSIX_ENTRY_CNT 128 /* TBD make it 512 */
-#define BF_MSI_ENTRY_CNT 2
-
-/* interrupt mode */
-enum bf_intr_mode {
- BF_INTR_MODE_NONE = 0,
- BF_INTR_MODE_LEGACY,
- BF_INTR_MODE_MSI,
- BF_INTR_MODE_MSIX
-};
-
-/* device memory */
-struct bf_dev_mem {
- const char *name;
- phys_addr_t addr;
- resource_size_t size;
- void __iomem *internal_addr;
-};
-
-struct bf_listener {
- struct bf_pci_dev *bfdev;
- s32 event_count[BF_MSIX_ENTRY_CNT];
- int minor;
- struct bf_listener *next;
-};
-
-/* device information */
-struct bf_dev_info {
- struct module *owner;
- struct device *dev;
- int minor;
- atomic_t event[BF_MSIX_ENTRY_CNT];
- wait_queue_head_t wait;
- const char *version;
- struct bf_dev_mem mem[BF_MAX_BAR_MAPS];
- struct msix_entry *msix_entries;
- long irq; /* first irq vector */
- int num_irq; /* number of irq vectors */
- unsigned long irq_flags;/* sharable ?? */
- int pci_error_state; /* was there a pci bus error */
-};
-
-/* cookie to be passed to IRQ handler, useful especially with MSIX */
-struct bf_int_vector {
- struct bf_pci_dev *bf_dev;
- int int_vec_offset;
-};
-
-
-/**
- * A structure describing the private information for a BF pcie device.
- */
-struct bf_pci_dev {
- struct bf_dev_info info;
- struct pci_dev *pdev;
- enum bf_intr_mode mode;
- u8 instance;
- char name[16];
- struct bf_int_vector bf_int_vec[BF_MSIX_ENTRY_CNT];
- struct bf_listener *listener_head; /* head of a singly linked list of
- listeners */
-};
-
/* Keep any global information here that must survive even after the
* bf_pci_dev is free-ed up.
*/
struct bf_global {
- struct bf_pci_dev *bfdev ;
+ struct bf_pci_dev *bfdev;
struct cdev *bf_cdev;
struct fasync_struct *async_queue;
};
@@ -181,14 +82,19 @@ static int bf_major;
static int bf_minor[BF_MAX_DEVICE_CNT] = {0};
static struct class *bf_class = NULL;
static char *intr_mode = NULL;
+static int kpkt_mode = 0;
+static int kpkt_hd_room = 32;
+static int kpkt_rx_count = 256;
+static int kpkt_dr_int_en = 1;
+
static enum bf_intr_mode bf_intr_mode_default = BF_INTR_MODE_MSI;
static spinlock_t bf_nonisr_lock;
+
/* dev->minor should index into this array */
static struct bf_global bf_global[BF_MAX_DEVICE_CNT];
static void bf_add_listener(struct bf_pci_dev *bfdev,
- struct bf_listener *listener)
-{
+ struct bf_listener *listener) {
struct bf_listener **cur_listener = &bfdev->listener_head;
if (!listener) {
@@ -197,7 +103,7 @@ static void bf_add_listener(struct bf_pci_dev *bfdev,
spin_lock(&bf_nonisr_lock);
while (*cur_listener) {
- cur_listener = &((*cur_listener)->next);
+ cur_listener = &((*cur_listener)->next);
}
*cur_listener = listener;
listener->next = NULL;
@@ -206,12 +112,12 @@ static void bf_add_listener(struct bf_pci_dev *bfdev,
}
static void bf_remove_listener(struct bf_pci_dev *bfdev,
- struct bf_listener *listener)
-{
+ struct bf_listener *listener) {
struct bf_listener **cur_listener = &bfdev->listener_head;
- /* in case of certain error conditions, this function might be called after bf_pci_remove()
- */
+ /* in case of certain error conditions, this function might be called after
+ * bf_pci_remove()
+ */
if (!bfdev || !listener) {
return;
}
@@ -235,12 +141,11 @@ static void bf_remove_listener(struct bf_pci_dev *bfdev,
/* a pool of minor numbers is maintained */
/* return the first available minor number */
-static int bf_get_next_minor_no(int *minor)
-{
+static int bf_get_next_minor_no(int *minor) {
int i;
spin_lock(&bf_nonisr_lock);
- for(i = 0; i < BF_MAX_DEVICE_CNT; i++) {
+ for (i = 0; i < BF_MAX_DEVICE_CNT; i++) {
if (bf_minor[i] == 0) {
*minor = i;
bf_minor[i] = 1; /* mark it as taken */
@@ -254,13 +159,12 @@ static int bf_get_next_minor_no(int *minor)
}
/* return a minor number back to the pool for recycling */
-static int bf_return_minor_no(int minor)
-{
+static int bf_return_minor_no(int minor) {
int err;
spin_lock(&bf_nonisr_lock);
if (bf_minor[minor] == 0) { /* was already returned */
- err = -1; /* don't change anything, but return error */
+ err = -1; /* don't change anything, but return error */
} else {
bf_minor[minor] = 0; /* mark it as available */
err = 0;
@@ -269,31 +173,29 @@ static int bf_return_minor_no(int minor)
return err;
}
-static inline struct bf_pci_dev *bf_get_pci_dev(struct bf_dev_info *info)
-{
- return container_of(info, struct bf_pci_dev, info);
+static inline struct bf_pci_dev *bf_get_pci_dev(struct bf_dev_info *info) {
+ return container_of(info, struct bf_pci_dev, info);
}
/*
* It masks the msix on/off of generating MSI-X messages.
*/
-static void
-bf_msix_mask_irq(struct msi_desc *desc, int32_t state)
-{
- u32 mask_bits = desc->masked;
- unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
- PCI_MSIX_ENTRY_VECTOR_CTRL;
-
- if (state != 0)
- mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;
- else
- mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
-
- if (mask_bits != desc->masked) {
- writel(mask_bits, desc->mask_base + offset);
- readl(desc->mask_base);
- desc->masked = mask_bits;
- }
+static void bf_msix_mask_irq(struct msi_desc *desc, int32_t state) {
+ u32 mask_bits = desc->masked;
+ unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_VECTOR_CTRL;
+
+ if (state != 0) {
+ mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;
+ } else {
+ mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
+ }
+
+ if (mask_bits != desc->masked) {
+ writel(mask_bits, desc->mask_base + offset);
+ readl(desc->mask_base);
+ desc->masked = mask_bits;
+ }
}
/**
@@ -308,179 +210,217 @@ bf_msix_mask_irq(struct msi_desc *desc, int32_t state)
* - On success, 0.
* - On failure, a negative value.
*/
-static int
-bf_pci_irqcontrol(struct bf_pci_dev *bfdev, s32 irq_state)
-{
- struct pci_dev *pdev = bfdev->pdev;
-
- pci_cfg_access_lock(pdev);
- if (bfdev->mode == BF_INTR_MODE_LEGACY)
- pci_intx(pdev, !!irq_state);
-
- else if (bfdev->mode == BF_INTR_MODE_MSIX) {
- struct msi_desc *desc;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
- list_for_each_entry(desc, &pdev->msi_list, list)
- bf_msix_mask_irq(desc, irq_state);
+static int bf_pci_irqcontrol(struct bf_pci_dev *bfdev, s32 irq_state) {
+ struct pci_dev *pdev = bfdev->pdev;
+
+ pci_cfg_access_lock(pdev);
+ if (bfdev->mode == BF_INTR_MODE_LEGACY) {
+ pci_intx(pdev, !!irq_state);
+ } else if (bfdev->mode == BF_INTR_MODE_MSIX) {
+ struct msi_desc *desc;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
+ list_for_each_entry(desc, &pdev->msi_list, list)
+ bf_msix_mask_irq(desc, irq_state);
#else
- for_each_pci_msi_entry(desc, pdev)
- bf_msix_mask_irq(desc, irq_state);
+ for_each_pci_msi_entry(desc, pdev) bf_msix_mask_irq(desc, irq_state);
#endif
- }
- pci_cfg_access_unlock(pdev);
+ }
+ pci_cfg_access_unlock(pdev);
- return 0;
+ return 0;
}
+#ifdef BF_INCLUDE_KPKT
+/* there are three TBUS MSIX vectors */
+static int bf_irq_is_tbus_msix(struct bf_pci_dev *bfdev, int irq) {
+ struct bf_dev_info *info = &bfdev->info;
+
+ if (!info->tbus_msix_map_enable) {
+ return 0;
+ }
+ if (irq == info->msix_entries[info->tbus_msix_ind[0]].vector ||
+ irq == info->msix_entries[info->tbus_msix_ind[1]].vector) {
+ return 1;
+ } else if (irq == info->msix_entries[info->tbus_msix_ind[2]].vector) {
+ /* log error */
+ printk(KERN_ALERT "bf_tbus error msix\n");
+ return 1;
+ }
+ return 0;
+}
+#endif
+
/**
* interrupt handler which will check if the interrupt is from the right
* device. If so, disable it here and will be enabled later.
*/
-static irqreturn_t bf_pci_irqhandler(int irq, struct bf_pci_dev *bfdev)
-{
- /* Legacy mode need to mask in hardware */
- if (bfdev->mode == BF_INTR_MODE_LEGACY &&
- !pci_check_and_mask_intx(bfdev->pdev))
- return IRQ_NONE;
-
- /* NOTE : if bfdev->info.pci_error_state == 1, then do not access the
- * device and return IRQ_NOTHANDLED.
- */
- /* Message signal mode, no share IRQ and automasked */
- return IRQ_HANDLED;
+static irqreturn_t bf_pci_irqhandler(int irq, struct bf_pci_dev *bfdev) {
+ /* Legacy mode need to mask in hardware */
+ if (bfdev->mode == BF_INTR_MODE_LEGACY &&
+ !pci_check_and_mask_intx(bfdev->pdev)) {
+ return IRQ_NONE;
+ }
+
+ /* NOTE : if bfdev->info.pci_error_state == 1, then do not access the
+ * device and return IRQ_NOTHANDLED.
+ */
+#ifdef BF_INCLUDE_KPKT
+ /* handle pkt DR interrpt (MSI vect-1) if it has to be in kernel */
+ if (kpkt_dr_int_en && bfdev->info.irq != 0) {
+ if (bfdev->mode == BF_INTR_MODE_LEGACY) {
+ bf_kpkt_irqhandler(irq, bfdev->adapter_ptr);
+ } else if (bfdev->mode == BF_INTR_MODE_MSI) {
+ /* do not process packet unless the MSI interrupt is from tbus */
+ /* all BF interrupts arrive on one single MSI if "1" MSI is configured */
+ if (bfdev->info.num_irq == 1 || (irq == (bfdev->info.irq + BF_MSI_INT_TBUS))) {
+ bf_kpkt_irqhandler(irq, bfdev->adapter_ptr);
+ }
+ } else if (bfdev->mode == BF_INTR_MODE_MSIX) {
+ if (bfdev->info.tof_type == BF_TOFINO_2 && bf_irq_is_tbus_msix(bfdev,irq)) {
+ bf_kpkt_irqhandler(irq, bfdev->adapter_ptr);
+ }
+ }
+ }
+#endif
+ /* Message signal mode, no share IRQ and automasked */
+ return IRQ_HANDLED;
}
/* Remap pci resources described by bar #pci_bar */
-static int
-bf_pci_setup_iomem(struct pci_dev *dev, struct bf_dev_info *info,
- int n, int pci_bar, const char *name)
-{
- unsigned long addr, len;
- void *internal_addr;
-
- if (sizeof(info->mem) / sizeof(info->mem[0]) <= n)
- return -EINVAL;
-
- addr = pci_resource_start(dev, pci_bar);
- len = pci_resource_len(dev, pci_bar);
- if (addr == 0 || len == 0)
- return -1;
- internal_addr = pci_ioremap_bar(dev, pci_bar);
- if (internal_addr == NULL)
- return -1;
- info->mem[n].name = name;
- info->mem[n].addr = addr;
- info->mem[n].internal_addr = internal_addr;
- info->mem[n].size = len;
- return 0;
+static int bf_pci_setup_iomem(struct pci_dev *dev,
+ struct bf_dev_info *info,
+ int n,
+ int pci_bar,
+ const char *name) {
+ unsigned long addr, len;
+ void *internal_addr;
+
+ if (sizeof(info->mem) / sizeof(info->mem[0]) <= n) {
+ return -EINVAL;
+ }
+
+ addr = pci_resource_start(dev, pci_bar);
+ len = pci_resource_len(dev, pci_bar);
+ if (addr == 0 || len == 0) {
+ return -1;
+ }
+ internal_addr = pci_ioremap_bar(dev, pci_bar);
+ if (internal_addr == NULL) {
+ return -1;
+ }
+ info->mem[n].name = name;
+ info->mem[n].addr = addr;
+ info->mem[n].internal_addr = internal_addr;
+ info->mem[n].size = len;
+ return 0;
}
/* Unmap previously ioremap'd resources */
-static void
-bf_pci_release_iomem(struct bf_dev_info *info)
-{
- int i;
+static void bf_pci_release_iomem(struct bf_dev_info *info) {
+ int i;
- for (i = 0; i < BF_MAX_BAR_MAPS; i++) {
- if (info->mem[i].internal_addr)
- iounmap(info->mem[i].internal_addr);
- }
+ for (i = 0; i < BF_MAX_BAR_MAPS; i++) {
+ if (info->mem[i].internal_addr) {
+ iounmap(info->mem[i].internal_addr);
+ }
+ }
}
-static int
-bf_setup_bars(struct pci_dev *dev, struct bf_dev_info *info)
-{
- int i, iom, ret;
- unsigned long flags;
- static const char *bar_names[BF_MAX_BAR_MAPS] = {
- "BAR0", "BAR1", "BAR2", "BAR3", "BAR4", "BAR5",
- };
-
- iom = 0;
-
- for (i = 0; i < BF_MAX_BAR_MAPS; i++) {
- if (pci_resource_len(dev, i) != 0 &&
- pci_resource_start(dev, i) != 0) {
- flags = pci_resource_flags(dev, i);
- if (flags & IORESOURCE_MEM) {
- ret = bf_pci_setup_iomem(dev, info, iom, i, bar_names[i]);
- if (ret != 0)
- return ret;
- iom++;
- }
- }
- }
- return (iom != 0) ? ret : -ENOENT;
+static int bf_setup_bars(struct pci_dev *dev, struct bf_dev_info *info) {
+ int i, iom, ret;
+ unsigned long flags;
+ static const char *bar_names[BF_MAX_BAR_MAPS] = {
+ "BAR0", "BAR1", "BAR2", "BAR3", "BAR4", "BAR5",
+ };
+
+ iom = 0;
+
+ for (i = 0; i < BF_MAX_BAR_MAPS; i++) {
+ if (pci_resource_len(dev, i) != 0 && pci_resource_start(dev, i) != 0) {
+ flags = pci_resource_flags(dev, i);
+ if (flags & IORESOURCE_MEM) {
+ ret = bf_pci_setup_iomem(dev, info, iom, i, bar_names[i]);
+ if (ret != 0) {
+ return ret;
+ }
+ iom++;
+ }
+ }
+ }
+ return (iom != 0) ? ret : -ENOENT;
}
-static irqreturn_t bf_interrupt(int irq, void *bfdev_id)
-{
+static irqreturn_t bf_interrupt(int irq, void *bfdev_id) {
struct bf_pci_dev *bfdev = ((struct bf_int_vector *)bfdev_id)->bf_dev;
int vect_off = ((struct bf_int_vector *)bfdev_id)->int_vec_offset;
irqreturn_t ret = bf_pci_irqhandler(irq, bfdev);
- if (ret == IRQ_HANDLED)
+ if (ret == IRQ_HANDLED) {
atomic_inc(&(bfdev->info.event[vect_off]));
-
+ }
return ret;
}
-static unsigned int bf_poll(struct file *filep, poll_table *wait)
-{
+static unsigned int bf_poll(struct file *filep, poll_table *wait) {
struct bf_listener *listener = (struct bf_listener *)filep->private_data;
struct bf_pci_dev *bfdev = listener->bfdev;
int i;
-
+
if (!bfdev) {
return -ENODEV;
}
- if (!bfdev->info.irq)
+ if (!bfdev->info.irq) {
return -EIO;
-
+ }
+
poll_wait(filep, &bfdev->info.wait, wait);
- for (i = 0; i < BF_MSIX_ENTRY_CNT; i++)
- if (listener->event_count[i] != atomic_read(&bfdev->info.event[i]))
+ for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) {
+ if (listener->event_count[i] != atomic_read(&bfdev->info.event[i])) {
return POLLIN | POLLRDNORM;
+ }
+ }
return 0;
}
-static int bf_find_mem_index(struct vm_area_struct *vma)
-{
+static int bf_find_mem_index(struct vm_area_struct *vma) {
struct bf_pci_dev *bfdev = vma->vm_private_data;
if (vma->vm_pgoff < BF_MAX_BAR_MAPS) {
- if (bfdev->info.mem[vma->vm_pgoff].size == 0)
+ if (bfdev->info.mem[vma->vm_pgoff].size == 0) {
return -1;
+ }
return (int)vma->vm_pgoff;
}
return -1;
}
-
+
static const struct vm_operations_struct bf_physical_vm_ops = {
#ifdef CONFIG_HAVE_IOREMAP_PROT
- .access = generic_access_phys,
+ .access = generic_access_phys,
#endif
};
-static int bf_mmap_physical(struct vm_area_struct *vma)
-{
+static int bf_mmap_physical(struct vm_area_struct *vma) {
struct bf_pci_dev *bfdev = vma->vm_private_data;
int bar = bf_find_mem_index(vma);
struct bf_dev_mem *mem;
- if (bar < 0)
+ if (bar < 0) {
return -EINVAL;
+ }
mem = bfdev->info.mem + bar;
-
- if (mem->addr & ~PAGE_MASK)
+
+ if (mem->addr & ~PAGE_MASK) {
return -ENODEV;
- if (vma->vm_end - vma->vm_start > mem->size)
+ }
+ if (vma->vm_end - vma->vm_start > mem->size) {
return -EINVAL;
-
+ }
+
vma->vm_ops = &bf_physical_vm_ops;
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
/*
* We cannot use the vm_iomap_memory() helper here,
* because vma->vm_pgoff is the map index we looked
@@ -490,40 +430,45 @@ static int bf_mmap_physical(struct vm_area_struct *vma)
* So we just do the physical mmap without a page
* offset.
*/
- return remap_pfn_range(vma, vma->vm_start, mem->addr >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start, vma->vm_page_prot);
+ return remap_pfn_range(vma,
+ vma->vm_start,
+ mem->addr >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
}
-static int bf_mmap(struct file *filep, struct vm_area_struct *vma)
-{
+static int bf_mmap(struct file *filep, struct vm_area_struct *vma) {
struct bf_listener *listener = filep->private_data;
struct bf_pci_dev *bfdev = listener->bfdev;
int bar;
unsigned long requested_pages, actual_pages;
-
+
if (!bfdev) {
return -ENODEV;
}
- if (vma->vm_end < vma->vm_start)
+ if (vma->vm_end < vma->vm_start) {
return -EINVAL;
-
+ }
+
vma->vm_private_data = bfdev;
-
+
bar = bf_find_mem_index(vma);
- if (bar < 0)
+ if (bar < 0) {
return -EINVAL;
-
+ }
+
requested_pages = vma_pages(vma);
- actual_pages = ((bfdev->info.mem[bar].addr & ~PAGE_MASK)
- + bfdev->info.mem[bar].size + PAGE_SIZE -1) >> PAGE_SHIFT;
- if (requested_pages > actual_pages)
+ actual_pages = ((bfdev->info.mem[bar].addr & ~PAGE_MASK) +
+ bfdev->info.mem[bar].size + PAGE_SIZE - 1) >>
+ PAGE_SHIFT;
+ if (requested_pages > actual_pages) {
return -EINVAL;
-
+ }
+
return bf_mmap_physical(vma);
}
-static int bf_fasync(int fd, struct file *filep, int mode)
-{
+static int bf_fasync(int fd, struct file *filep, int mode) {
int minor;
if (!filep->private_data) {
@@ -539,8 +484,7 @@ static int bf_fasync(int fd, struct file *filep, int mode)
return (fasync_helper(fd, filep, mode, &bf_global[minor].async_queue));
}
-static int bf_open(struct inode *inode, struct file *filep)
-{
+static int bf_open(struct inode *inode, struct file *filep) {
struct bf_pci_dev *bfdev;
struct bf_listener *listener;
int i;
@@ -550,19 +494,19 @@ static int bf_open(struct inode *inode, struct file *filep)
if (listener) {
listener->bfdev = bfdev;
listener->minor = bfdev->info.minor;
- listener->next = NULL;
+ listener->next = NULL;
bf_add_listener(bfdev, listener);
- for (i = 0; i < BF_MSIX_ENTRY_CNT; i++)
+ for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) {
listener->event_count[i] = atomic_read(&bfdev->info.event[i]);
+ }
filep->private_data = listener;
return 0;
} else {
- return(-ENOMEM);
+ return (-ENOMEM);
}
}
-static int bf_release(struct inode *inode, struct file *filep)
-{
+static int bf_release(struct inode *inode, struct file *filep) {
struct bf_listener *listener = filep->private_data;
bf_fasync(-1, filep, 0); /* empty any process id in the notification list */
@@ -574,42 +518,47 @@ static int bf_release(struct inode *inode, struct file *filep)
}
/* user space support: make read() system call after poll() of select() */
-static ssize_t bf_read(struct file *filep, char __user *buf,
- size_t count, loff_t *ppos)
-{
+static ssize_t bf_read(struct file *filep,
+ char __user *buf,
+ size_t count,
+ loff_t *ppos) {
struct bf_listener *listener = filep->private_data;
struct bf_pci_dev *bfdev = listener->bfdev;
int retval, event_count[BF_MSIX_ENTRY_CNT];
- int i, mismatch_found = 0; /* OR of per vector mismatch */
+ int i, mismatch_found = 0; /* OR of per vector mismatch */
unsigned char cnt_match[BF_MSIX_ENTRY_CNT]; /* per vector mismatch */
if (!bfdev) {
return -ENODEV;
}
/* irq must be setup for read() to work */
- if (!bfdev->info.irq)
+ if (!bfdev->info.irq) {
return -EIO;
+ }
/* ensure that there is enough space on user buffer for the given interrupt
* mode */
if (bfdev->mode == BF_INTR_MODE_MSIX) {
- if (count < sizeof(s32)*BF_MSIX_ENTRY_CNT)
+ if (count < sizeof(s32) * BF_MSIX_ENTRY_CNT) {
return -EINVAL;
- count = sizeof(s32)*BF_MSIX_ENTRY_CNT;
+ }
+ count = sizeof(s32) * BF_MSIX_ENTRY_CNT;
} else if (bfdev->mode == BF_INTR_MODE_MSI) {
- if (count < sizeof(s32)*BF_MSI_ENTRY_CNT)
+ if (count < sizeof(s32) * BF_MSI_ENTRY_CNT) {
return -EINVAL;
- count = sizeof(s32)*BF_MSI_ENTRY_CNT;
+ }
+ count = sizeof(s32) * BF_MSI_ENTRY_CNT;
} else {
- if (count < sizeof(s32))
+ if (count < sizeof(s32)) {
return -EINVAL;
+ }
count = sizeof(s32);
}
do {
set_current_state(TASK_INTERRUPTIBLE);
- for (i = 0; i < (count/sizeof(s32)); i++) {
+ for (i = 0; i < (count / sizeof(s32)); i++) {
event_count[i] = atomic_read(&(bfdev->info.event[i]));
if (event_count[i] != listener->event_count[i]) {
mismatch_found |= 1;
@@ -621,10 +570,10 @@ static ssize_t bf_read(struct file *filep, char __user *buf,
}
if (mismatch_found) {
__set_current_state(TASK_RUNNING);
- if (copy_to_user(buf, &event_count, count))
+ if (copy_to_user(buf, &event_count, count)) {
retval = -EFAULT;
- else { /* adjust the listener->event_count; */
- for (i = 0 ; i < (count/sizeof(s32)); i++) {
+ } else { /* adjust the listener->event_count; */
+ for (i = 0; i < (count / sizeof(s32)); i++) {
if (cnt_match[i]) {
listener->event_count[i] = event_count[i];
}
@@ -651,25 +600,29 @@ static ssize_t bf_read(struct file *filep, char __user *buf,
return retval;
}
-/* user space is supposed to call this after it is done with interrupt
+/* user space is supposed to call this after it is done with interrupt
* processing
*/
-static ssize_t bf_write(struct file *filep, const char __user *buf,
- size_t count, loff_t *ppos)
-{
+static ssize_t bf_write(struct file *filep,
+ const char __user *buf,
+ size_t count,
+ loff_t *ppos) {
struct bf_listener *listener = filep->private_data;
struct bf_pci_dev *bfdev = listener->bfdev;
ssize_t ret;
s32 int_en;
- if (!bfdev || !bfdev->info.irq)
+ if (!bfdev || !bfdev->info.irq) {
return -EIO;
-
- if (count != sizeof(s32))
+ }
+
+ if (count != sizeof(s32)) {
return -EINVAL;
+ }
- if (copy_from_user(&int_en, buf, count))
+ if (copy_from_user(&int_en, buf, count)) {
return -EFAULT;
+ }
/* clear pci_error_state */
bfdev->info.pci_error_state = 0;
@@ -692,7 +645,11 @@ static long bf_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
}
switch(cmd) {
case BF_IOCMAPDMAADDR:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
+ if (access_ok(addr, sizeof(bf_dma_bus_map_t))) {
+#else
if (access_ok(VERIFY_WRITE, addr, sizeof(bf_dma_bus_map_t))) {
+#endif
if (copy_from_user(&dma_map, addr, sizeof(bf_dma_bus_map_t))) {
return EFAULT;
}
@@ -703,7 +660,7 @@ static long bf_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
if (dma_mapping_error(&bfdev->pdev->dev, dma_hndl)) {
return EFAULT;
}
- dma_map.dma_addr = (void *)dma_hndl;
+ dma_map.dma_addr = (void *)(uintptr_t)dma_hndl;
if (copy_to_user(addr, &dma_map, sizeof(bf_dma_bus_map_t))) {
return EFAULT;
}
@@ -712,18 +669,55 @@ static long bf_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
}
break;
case BF_IOCUNMAPDMAADDR:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
+ if (access_ok(addr, sizeof(bf_dma_bus_map_t))) {
+#else
if (access_ok(VERIFY_READ, addr, sizeof(bf_dma_bus_map_t))) {
+#endif
if (copy_from_user(&dma_map, addr, sizeof(bf_dma_bus_map_t))) {
return EFAULT;
}
if (!dma_map.dma_addr || !dma_map.size) {
return EFAULT;
}
- dma_unmap_single(&bfdev->pdev->dev, (dma_addr_t)dma_map.dma_addr, dma_map.size, DMA_BIDIRECTIONAL);
+ dma_unmap_single(&bfdev->pdev->dev, (dma_addr_t)(uintptr_t)(dma_map.dma_addr), dma_map.size, DMA_BIDIRECTIONAL);
} else {
return EFAULT;
}
break;
+ case BF_TBUS_MSIX_INDEX:
+ /* not supported for Tofino-1 */
+ if (bfdev->info.tof_type == BF_TOFINO_1) {
+ return EINVAL;
+ } else {
+ int i;
+ bf_tbus_msix_indices_t msix_ind;
+ if (copy_from_user(&msix_ind, addr, sizeof(bf_tbus_msix_indices_t))) {
+ return EFAULT;
+ }
+ if (msix_ind.cnt > BF_TBUS_MSIX_INDICES_MAX) {
+ return EINVAL;
+ }
+ for (i = 0; i < msix_ind.cnt; i++) {
+ if (msix_ind.indices[i] >= BF_MSIX_ENTRY_CNT) {
+ return EINVAL;
+ }
+ }
+ for (i = 0; i < msix_ind.cnt; i++) {
+ bfdev->info.tbus_msix_ind[i] = msix_ind.indices[i];
+ }
+ bfdev->info.tbus_msix_map_enable = 1;
+ }
+ break;
+ case BF_GET_INTR_MODE:
+ {
+ bf_intr_mode_t i_mode;
+ i_mode.intr_mode = bfdev->mode;
+ if (copy_to_user(addr, &i_mode, sizeof(bf_intr_mode_t))) {
+ return EFAULT;
+ }
+ }
+ break;
default:
return EINVAL;
}
@@ -731,27 +725,27 @@ static long bf_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
}
static const struct file_operations bf_fops = {
- .owner = THIS_MODULE,
- .open = bf_open,
- .release = bf_release,
- .unlocked_ioctl = bf_ioctl,
- .read = bf_read,
- .write = bf_write,
- .mmap = bf_mmap,
- .poll = bf_poll,
- .fasync = bf_fasync,
+ .owner = THIS_MODULE,
+ .open = bf_open,
+ .release = bf_release,
+ .unlocked_ioctl = bf_ioctl,
+ .read = bf_read,
+ .write = bf_write,
+ .mmap = bf_mmap,
+ .poll = bf_poll,
+ .fasync = bf_fasync,
};
-static int bf_major_init(struct bf_pci_dev *bfdev, int minor)
-{
+static int bf_major_init(struct bf_pci_dev *bfdev, int minor) {
struct cdev *cdev;
static const char name[] = "bf";
dev_t bf_dev = 0;
int result;
result = alloc_chrdev_region(&bf_dev, 0, BF_MAX_DEVICE_CNT, name);
- if (result)
+ if (result) {
return result;
+ }
result = -ENOMEM;
cdev = cdev_alloc();
@@ -763,8 +757,9 @@ static int bf_major_init(struct bf_pci_dev *bfdev, int minor)
kobject_set_name(&cdev->kobj, "%s", name);
result = cdev_add(cdev, bf_dev, BF_MAX_DEVICE_CNT);
- if (result)
+ if (result) {
goto fail_dev_add;
+ }
bf_major = MAJOR(bf_dev);
bf_global[minor].bf_cdev = cdev;
@@ -775,19 +770,16 @@ static int bf_major_init(struct bf_pci_dev *bfdev, int minor)
return result;
}
-static void bf_major_cleanup(struct bf_pci_dev *bfdev, int minor)
-{
+static void bf_major_cleanup(struct bf_pci_dev *bfdev, int minor) {
unregister_chrdev_region(MKDEV(bf_major, 0), BF_MAX_DEVICE_CNT);
cdev_del(bf_global[minor].bf_cdev);
}
-static int bf_init_cdev(struct bf_pci_dev *bfdev, int minor)
-{
+static int bf_init_cdev(struct bf_pci_dev *bfdev, int minor) {
int ret;
ret = bf_major_init(bfdev, minor);
- if (ret)
- return ret;
-
+ if (ret) return ret;
+
bf_class = class_create(THIS_MODULE, BF_CLASS_NAME);
if (!bf_class) {
printk(KERN_ERR "create_class failed for bf_dev\n");
@@ -801,28 +793,26 @@ static int bf_init_cdev(struct bf_pci_dev *bfdev, int minor)
return ret;
}
-static void bf_remove_cdev(struct bf_pci_dev *bfdev)
-{
+static void bf_remove_cdev(struct bf_pci_dev *bfdev) {
class_destroy(bf_class);
bf_major_cleanup(bfdev, bfdev->info.minor);
}
-
/**
* bf_register_device - register a new userspace mem device
* @parent: parent device
- * @bfdev: bf pci device
+ * @bfdev: bf pci device
*
* returns zero on success or a negative error code.
*/
-int bf_register_device(struct device *parent, struct bf_pci_dev *bfdev)
-{
+int bf_register_device(struct device *parent, struct bf_pci_dev *bfdev) {
struct bf_dev_info *info = &bfdev->info;
int i, j, ret = 0;
int minor;
- if (!parent || !info || !info->version)
+ if (!parent || !info || !info->version) {
return -EINVAL;
+ }
init_waitqueue_head(&info->wait);
@@ -840,9 +830,8 @@ int bf_register_device(struct device *parent, struct bf_pci_dev *bfdev)
return ret;
}
- info->dev = device_create(bf_class, parent,
- MKDEV(bf_major, minor), bfdev,
- "bf%d", minor);
+ info->dev = device_create(
+ bf_class, parent, MKDEV(bf_major, minor), bfdev, "bf%d", minor);
if (!info->dev) {
printk(KERN_ERR "BF: device creation failed\n");
return -ENODEV;
@@ -861,19 +850,24 @@ int bf_register_device(struct device *parent, struct bf_pci_dev *bfdev)
* freed until they are released.
*/
if (bfdev->mode == BF_INTR_MODE_LEGACY) {
- ret = request_irq(info->irq, bf_interrupt,
- info->irq_flags, bfdev->name,
+ ret = request_irq(info->irq,
+ bf_interrupt,
+ info->irq_flags,
+ bfdev->name,
(void *)&(bfdev->bf_int_vec[0]));
if (ret) {
printk(KERN_ERR "bf failed to request legacy irq %ld error %d\n",
- info->irq, ret);
+ info->irq,
+ ret);
return ret;
}
printk(KERN_NOTICE "BF allocating legacy int vector %ld\n", info->irq);
} else if (bfdev->mode == BF_INTR_MODE_MSIX) {
for (i = 0; i < info->num_irq; i++) {
- ret = request_irq(info->msix_entries[i].vector, bf_interrupt,
- info->irq_flags, bfdev->name,
+ ret = request_irq(info->msix_entries[i].vector,
+ bf_interrupt,
+ info->irq_flags,
+ bfdev->name,
(void *)&(bfdev->bf_int_vec[i]));
if (ret) {
/* undo all other previous bindings */
@@ -883,14 +877,17 @@ int bf_register_device(struct device *parent, struct bf_pci_dev *bfdev)
(void *)&(bfdev->bf_int_vec[j]));
}
return ret;
- }
+ }
}
printk(KERN_NOTICE "BF allocating %d MSIx vectors from %ld\n",
- info->num_irq, info->irq);
+ info->num_irq,
+ info->irq);
} else if (bfdev->mode == BF_INTR_MODE_MSI) {
for (i = 0; i < info->num_irq; i++) {
- ret = request_irq(info->irq + i, bf_interrupt,
- info->irq_flags, bfdev->name,
+ ret = request_irq(info->irq + i,
+ bf_interrupt,
+ info->irq_flags,
+ bfdev->name,
(void *)&(bfdev->bf_int_vec[i]));
if (ret) {
/* undo all other previous bindings */
@@ -899,10 +896,11 @@ int bf_register_device(struct device *parent, struct bf_pci_dev *bfdev)
free_irq(info->irq + j, (void *)&(bfdev->bf_int_vec[j]));
}
return ret;
- }
+ }
}
printk(KERN_NOTICE "BF allocating %d MSI vectors from %ld\n",
- info->num_irq, info->irq);
+ info->num_irq,
+ info->irq);
}
}
return 0;
@@ -910,12 +908,11 @@ int bf_register_device(struct device *parent, struct bf_pci_dev *bfdev)
/**
* bf_unregister_device - register a new userspace mem device
- * @bfdev: bf pci device
+ * @bfdev: bf pci device
*
* returns none
*/
-void bf_unregister_device(struct bf_pci_dev *bfdev)
-{
+void bf_unregister_device(struct bf_pci_dev *bfdev) {
struct bf_dev_info *info = &bfdev->info;
int i;
@@ -938,8 +935,7 @@ void bf_unregister_device(struct bf_pci_dev *bfdev)
return;
}
-static inline struct device *pci_dev_to_dev(struct pci_dev *pdev)
-{
+static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) {
return &pdev->dev;
}
@@ -957,7 +953,7 @@ static void bf_disable_int_dma(struct bf_pci_dev *bfdev) {
/* mask interrupt at shadow level */
bf_addr = (u32 *)((u8 *)bf_base_addr + 0xc0);
for (i = 0; i < 16; i++) {
- *bf_addr = 0xffffffff;
+ *bf_addr = 0xffffffffUL;
bf_addr++;
}
/* mask DMA */
@@ -967,18 +963,17 @@ static void bf_disable_int_dma(struct bf_pci_dev *bfdev) {
*bf_addr = val;
}
-static int
-bf_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
+static int bf_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) {
struct bf_pci_dev *bfdev;
- int err;
+ int err, pci_use_highmem;
int i, num_irq;
memset(bf_global, 0, sizeof(bf_global));
bfdev = kzalloc(sizeof(struct bf_pci_dev), GFP_KERNEL);
- if (!bfdev)
+ if (!bfdev) {
return -ENOMEM;
+ }
/* init the cookies to be passed to ISRs */
for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) {
@@ -992,12 +987,32 @@ bf_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* clear pci_error_state */
bfdev->info.pci_error_state = 0;
+ /* mark pci device_id type */
+ bfdev->info.pci_dev_id = pdev->device;
+ switch (pdev->device) {
+ case TOFINO2_DEV_ID_A0:
+ case TOFINO2_DEV_ID_A00:
+ case TOFINO2_DEV_ID_B0:
+ bfdev->info.tof_type = BF_TOFINO_2;
+ break;
+ default:
+ bfdev->info.tof_type = BF_TOFINO_1;
+ break;
+ }
+ /* intialize TBUS MSIX indices */
+ for (i = 0; i < BF_TBUS_MSIX_INDICES_MAX; i++) {
+ if (bfdev->info.tof_type == BF_TOFINO_1) {
+ bfdev->info.tbus_msix_ind[i] = BF_TBUS_MSIX_BASE_INDEX_TOF1 + i;
+ } else if (bfdev->info.tof_type == BF_TOFINO_2) {
+ bfdev->info.tbus_msix_ind[i] = BF_TBUS_MSIX_INDEX_INVALID;
+ }
+ }
/*
* enable device
*/
err = pci_enable_device(pdev);
if (err != 0) {
- dev_err(&pdev->dev, "Cannot enable PCI device\n");
+ printk(KERN_ERR "bf cannot enable PCI device\n");
goto fail_free;
}
@@ -1007,27 +1022,29 @@ bf_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
*/
err = pci_request_regions(pdev, "bf_umem");
if (err != 0) {
- dev_err(&pdev->dev, "Cannot request regions\n");
+ printk(KERN_ERR "bf Cannot request regions\n");
goto fail_pci_disable;
}
/* remap IO memory */
err = bf_setup_bars(pdev, &bfdev->info);
- if (err != 0)
+ if (err != 0) {
+ printk(KERN_ERR "bf Cannot setup BARs\n");
goto fail_release_iomem;
+ }
if (!dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(64)) &&
!dma_set_coherent_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(64))) {
+ pci_use_highmem = 1;
} else {
err = dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(32));
if (err) {
- err = dma_set_coherent_mask(pci_dev_to_dev(pdev),
- DMA_BIT_MASK(32));
+ err = dma_set_coherent_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(32));
if (err) {
- dev_err(pci_dev_to_dev(pdev), "No usable DMA "
- "configuration, aborting\n");
- goto fail_release_iomem;
+ printk(KERN_ERR "bf no usable DMA configuration, aborting\n");
+ goto fail_release_iomem;
}
}
+ pci_use_highmem = 0;
}
/* enable pci error reporting */
@@ -1054,126 +1071,142 @@ bf_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
switch (bf_intr_mode_default) {
#ifdef CONFIG_PCI_MSI
- case BF_INTR_MODE_MSIX:
- /* Only 1 msi-x vector needed */
- bfdev->info.msix_entries = kcalloc(BF_MSIX_ENTRY_CNT,
- sizeof(struct msix_entry), GFP_KERNEL);
- if (!bfdev->info.msix_entries) {
- err = -ENOMEM;
- goto fail_clear_pci_master;
- }
- for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) {
- bfdev->info.msix_entries[i].entry= i;
- }
+ case BF_INTR_MODE_MSIX:
+ /* Only 1 msi-x vector needed */
+ bfdev->info.msix_entries =
+ kcalloc(BF_MSIX_ENTRY_CNT, sizeof(struct msix_entry), GFP_KERNEL);
+ if (!bfdev->info.msix_entries) {
+ err = -ENOMEM;
+ goto fail_clear_pci_master;
+ }
+ for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) {
+ bfdev->info.msix_entries[i].entry = i;
+ }
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
- num_irq = pci_enable_msix(pdev, bfdev->info.msix_entries,
- BF_MSIX_ENTRY_CNT);
- if (num_irq == 0) {
- dev_dbg(&pdev->dev, "using MSI-X");
- bfdev->info.num_irq = BF_MSIX_ENTRY_CNT;
- bfdev->info.irq = bfdev->info.msix_entries[0].vector;
- bfdev->mode = BF_INTR_MODE_MSIX;
- printk(KERN_DEBUG "bf using %d MSIX irq from %ld\n", num_irq,
- bfdev->info.irq);
- break;
- }
+ num_irq = pci_enable_msix(pdev, bfdev->info.msix_entries,
+ BF_MSIX_ENTRY_CNT);
+ if (num_irq == 0) {
+ bfdev->info.num_irq = BF_MSIX_ENTRY_CNT;
+ bfdev->info.irq = bfdev->info.msix_entries[0].vector;
+ bfdev->mode = BF_INTR_MODE_MSIX;
+ printk(KERN_DEBUG "bf using %d MSIX irq from %ld\n", num_irq,
+ bfdev->info.irq);
+ break;
+ }
#else
- num_irq = pci_enable_msix_range(pdev, bfdev->info.msix_entries,
- BF_MSIX_ENTRY_CNT, BF_MSIX_ENTRY_CNT);
- if (num_irq == BF_MSIX_ENTRY_CNT) {
- dev_dbg(&pdev->dev, "using MSI-X");
- bfdev->info.num_irq = num_irq;
- bfdev->info.irq = bfdev->info.msix_entries[0].vector;
- bfdev->mode = BF_INTR_MODE_MSIX;
- printk(KERN_DEBUG "bf using %d MSIX irq from %ld\n", num_irq,
- bfdev->info.irq);
- break;
- } else {
- if (num_irq)
- pci_disable_msix(pdev);
- kfree(bfdev->info.msix_entries);
- bfdev->info.msix_entries = NULL;
- printk(KERN_ERR "bf error allocating MSIX vectors. Trying MSI...\n");
- /* and, fall back to MSI */
- }
+ num_irq = pci_enable_msix_range(
+ pdev, bfdev->info.msix_entries, BF_MSIX_ENTRY_CNT, BF_MSIX_ENTRY_CNT);
+ if (num_irq == BF_MSIX_ENTRY_CNT) {
+ bfdev->info.num_irq = num_irq;
+ bfdev->info.irq = bfdev->info.msix_entries[0].vector;
+ bfdev->mode = BF_INTR_MODE_MSIX;
+ printk(KERN_DEBUG "bf using %d MSIX irq from %ld\n",
+ num_irq,
+ bfdev->info.irq);
+ break;
+ } else {
+ if (num_irq) pci_disable_msix(pdev);
+ kfree(bfdev->info.msix_entries);
+ bfdev->info.msix_entries = NULL;
+ printk(KERN_ERR "bf error allocating MSIX vectors. Trying MSI...\n");
+ /* and, fall back to MSI */
+ }
#endif /* LINUX_VERSION_CODE */
/* ** intentional no-break */
- case BF_INTR_MODE_MSI:
+ case BF_INTR_MODE_MSI:
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
- num_irq = pci_enable_msi_block(pdev, BF_MSI_ENTRY_CNT);
- /* we must get requested number of MSI vectors enabled */
- if (num_irq == 0) {
- dev_dbg(&pdev->dev, "using MSI");
- bfdev->info.num_irq = BF_MSI_ENTRY_CNT;
- bfdev->info.irq = pdev->irq;
- bfdev->mode = BF_INTR_MODE_MSI;
- printk(KERN_DEBUG "bf using %d MSI irq from %ld\n", bfdev->info.num_irq,
+ num_irq = pci_enable_msi_block(pdev, BF_MSI_ENTRY_CNT);
+ /* we must get requested number of MSI vectors enabled */
+ if (num_irq == 0) {
+ bfdev->info.num_irq = BF_MSI_ENTRY_CNT;
+ bfdev->info.irq = pdev->irq;
+ bfdev->mode = BF_INTR_MODE_MSI;
+ printk(KERN_DEBUG "bf using %d MSI irq from %ld\n", bfdev->info.num_irq,
bfdev->info.irq);
- break;
- }
+ break;
+ }
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
- num_irq = pci_enable_msi_range(pdev, BF_MSI_ENTRY_CNT, BF_MSI_ENTRY_CNT);
- if (num_irq > 0) {
- dev_dbg(&pdev->dev, "using MSI");
- bfdev->info.num_irq = num_irq;
- bfdev->info.irq = pdev->irq;
- bfdev->mode = BF_INTR_MODE_MSI;
- printk(KERN_DEBUG "bf using %d MSI irq from %ld\n", bfdev->info.num_irq,
- bfdev->info.irq);
- break;
- }
+ num_irq = pci_enable_msi_range(pdev, BF_MSI_ENTRY_CNT, BF_MSI_ENTRY_CNT);
+ if (num_irq > 0) {
+ bfdev->info.num_irq = num_irq;
+ bfdev->info.irq = pdev->irq;
+ bfdev->mode = BF_INTR_MODE_MSI;
+ printk(KERN_DEBUG "bf using %d MSI irq from %ld\n",
+ bfdev->info.num_irq,
+ bfdev->info.irq);
+ break;
+ }
#else
- num_irq = pci_alloc_irq_vectors_affinity(pdev, BF_MSI_ENTRY_CNT,
- BF_MSI_ENTRY_CNT, PCI_IRQ_MSI | PCI_IRQ_AFFINITY, NULL);
- if (num_irq > 0) {
- dev_dbg(&pdev->dev, "using MSI");
- bfdev->info.num_irq = num_irq;
- bfdev->info.irq = pci_irq_vector(pdev, 0);
- bfdev->mode = BF_INTR_MODE_MSI;
- printk(KERN_DEBUG "bf using %d MSI irq from %ld\n", bfdev->info.num_irq,
+ num_irq = pci_alloc_irq_vectors_affinity(pdev, BF_MSI_ENTRY_CNT,
+ BF_MSI_ENTRY_CNT, PCI_IRQ_MSI | PCI_IRQ_AFFINITY, NULL);
+ if (num_irq > 0) {
+ bfdev->info.num_irq = num_irq;
+ bfdev->info.irq = pci_irq_vector(pdev, 0);
+ bfdev->mode = BF_INTR_MODE_MSI;
+ printk(KERN_DEBUG "bf using %d MSI irq from %ld\n", bfdev->info.num_irq,
bfdev->info.irq);
- break;
- }
+ break;
+ }
#endif /* LINUX_VERSION_CODE */
#endif /* CONFIG_PCI_MSI */
/* fall back to Legacy Interrupt, intentional no-break */
- case BF_INTR_MODE_LEGACY:
- if (pci_intx_mask_supported(pdev)) {
- dev_dbg(&pdev->dev, "using INTX");
- bfdev->info.irq_flags = IRQF_SHARED;
- bfdev->info.irq = pdev->irq;
- bfdev->mode = BF_INTR_MODE_LEGACY;
- printk(KERN_DEBUG "bf using LEGACY irq %ld\n", bfdev->info.irq);
- break;
- }
- dev_notice(&pdev->dev, "PCI INTx mask not supported\n");
+ case BF_INTR_MODE_LEGACY:
+ if (pci_intx_mask_supported(pdev)) {
+ bfdev->info.irq_flags = IRQF_SHARED;
+ bfdev->info.irq = pdev->irq;
+ bfdev->mode = BF_INTR_MODE_LEGACY;
+ printk(KERN_DEBUG "bf using LEGACY irq %ld\n", bfdev->info.irq);
+ break;
+ }
+ printk(KERN_NOTICE " bf PCI INTx mask not supported\n");
/* fall back to no Interrupt, intentional no-break */
- case BF_INTR_MODE_NONE:
- bfdev->info.irq = 0;
- bfdev->info.num_irq = 0;
- bfdev->mode = BF_INTR_MODE_NONE;
- break;
+ case BF_INTR_MODE_NONE:
+ bfdev->info.irq = 0;
+ bfdev->info.num_irq = 0;
+ bfdev->mode = BF_INTR_MODE_NONE;
+ break;
- default:
- dev_err(&pdev->dev, "invalid IRQ mode %u", bf_intr_mode_default);
- err = -EINVAL;
- goto fail_clear_pci_master;
+ default:
+ printk(KERN_DEBUG "bf invalid IRQ mode %u", bf_intr_mode_default);
+ err = -EINVAL;
+ goto fail_clear_pci_master;
}
pci_set_drvdata(pdev, bfdev);
sprintf(bfdev->name, "bf_%d", bfdev->info.minor);
/* register bf driver */
err = bf_register_device(&pdev->dev, bfdev);
- if (err != 0)
+ if (err != 0) {
goto fail_release_irq;
+ }
bf_global[bfdev->info.minor].async_queue = NULL;
bf_global[bfdev->info.minor].bfdev = bfdev;
- dev_info(&pdev->dev, "bf device %d registered with irq %ld\n",
- bfdev->instance, bfdev->info.irq);
+ dev_info(&pdev->dev,
+ "bf device %d registered with irq %ld\n",
+ bfdev->instance,
+ bfdev->info.irq);
printk(KERN_ALERT "bf probe ok\n");
+#ifdef BF_INCLUDE_KPKT
+ if (kpkt_mode) {
+ err = bf_kpkt_init(pdev,
+ bfdev->info.mem[0].internal_addr,
+ &bfdev->adapter_ptr,
+ bfdev->info.minor,
+ pci_use_highmem,
+ kpkt_hd_room,
+ kpkt_dr_int_en,
+ kpkt_rx_count);
+ if (err == 0) {
+ printk(KERN_ALERT "bf_kpkt kernel processing enabled\n");
+ } else {
+ printk(KERN_ALERT "error starting bf_kpkt kernel processing\n");
+ bfdev->adapter_ptr = NULL;
+ }
+ }
+#endif
return 0;
fail_release_irq:
@@ -1182,11 +1215,11 @@ bf_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_disable_msix(bfdev->pdev);
kfree(bfdev->info.msix_entries);
bfdev->info.msix_entries = NULL;
- }
- else if (bfdev->mode == BF_INTR_MODE_MSI)
+ } else if (bfdev->mode == BF_INTR_MODE_MSI) {
pci_disable_msi(bfdev->pdev);
+ }
fail_clear_pci_master:
- pci_clear_master(pdev);
+ pci_clear_master(pdev);
fail_release_iomem:
bf_pci_release_iomem(&bfdev->info);
pci_release_regions(pdev);
@@ -1199,22 +1232,24 @@ bf_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return err;
}
-
-static void
-bf_pci_remove(struct pci_dev *pdev)
-{
+static void bf_pci_remove(struct pci_dev *pdev) {
struct bf_pci_dev *bfdev = pci_get_drvdata(pdev);
struct bf_listener *cur_listener;
+#ifdef BF_INCLUDE_KPKT
+ if (kpkt_mode) {
+ bf_kpkt_remove(bfdev->adapter_ptr);
+ }
+#endif
bf_disable_int_dma(bfdev);
bf_unregister_device(bfdev);
if (bfdev->mode == BF_INTR_MODE_MSIX) {
pci_disable_msix(pdev);
kfree(bfdev->info.msix_entries);
bfdev->info.msix_entries = NULL;
- }
- else if (bfdev->mode == BF_INTR_MODE_MSI)
+ } else if (bfdev->mode == BF_INTR_MODE_MSI) {
pci_disable_msi(pdev);
+ }
pci_clear_master(pdev);
bf_pci_release_iomem(&bfdev->info);
pci_release_regions(pdev);
@@ -1234,6 +1269,17 @@ bf_pci_remove(struct pci_dev *pdev)
kfree(bfdev);
}
+/* AER support callbacks. Refer to:
+ * https://www.kernel.org/doc/Documentation/PCI/pcieaer-howto.txt
+ * and
+ * https://www.kernel.org/doc/Documentation/PCI/pci-error-recovery.txt
+ *
+ * from bf_kdrv point of view, AER uncorrected errors (fatal and non-fatal)
+ * should not cause pci link reset (upstream port AER callbacks must also
+ * support this requirements of bf_kdrv)
+ * Device, however, is not expected to function after uncorrected errors
+ * but, application has chance to perform diags without resetting pci link
+ */
/**
* bf_pci_error_detected - called when PCI error is detected
* @pdev: Pointer to PCI device
@@ -1242,10 +1288,8 @@ bf_pci_remove(struct pci_dev *pdev)
* called when root complex detects pci error associated with the device
*/
static pci_ers_result_t bf_pci_error_detected(struct pci_dev *pdev,
- pci_channel_state_t state)
-{
+ pci_channel_state_t state) {
struct bf_pci_dev *bfdev = pci_get_drvdata(pdev);
- int minor;
if (!bfdev) {
return PCI_ERS_RESULT_NONE;
@@ -1253,15 +1297,35 @@ static pci_ers_result_t bf_pci_error_detected(struct pci_dev *pdev,
printk(KERN_ERR "pci_err_detected state %d\n", state);
if (state == pci_channel_io_perm_failure || state == pci_channel_io_frozen) {
bfdev->info.pci_error_state = 1;
+#ifdef BF_INCLUDE_KPKT
+ if (kpkt_mode) {
+ bf_kpkt_set_pci_error(bfdev->adapter_ptr, 1);
+ }
+#endif
+ /* we do not want pci link to go down. The user space application
+ * should collect the diag info, terminate the application and unload the
+ * kernel module
+ */
+ return PCI_ERS_RESULT_CAN_RECOVER; /* to prevent pci link down */
+ } else {
+ return PCI_ERS_RESULT_CAN_RECOVER;
+ }
+}
+
+static pci_ers_result_t bf_pci_mmio_enabled(struct pci_dev *dev) {
+ struct bf_pci_dev *bfdev = pci_get_drvdata(dev);
+
+ printk(KERN_ERR "BF pci_mmio_enabled invoked after pci error\n");
+ pci_cleanup_aer_uncorrect_error_status(dev);
+
+ if (bfdev) {
/* send a signal to the user space program of the error */
- minor = bfdev->info.minor;
+ int minor = bfdev->info.minor;
if (minor < BF_MAX_DEVICE_CNT && bf_global[minor].async_queue) {
kill_fasync(&bf_global[minor].async_queue, SIGIO, POLL_ERR);
}
- return PCI_ERS_RESULT_DISCONNECT;
- } else {
- return PCI_ERS_RESULT_NONE;
}
+ return PCI_ERS_RESULT_RECOVERED;
}
/**
@@ -1270,13 +1334,13 @@ static pci_ers_result_t bf_pci_error_detected(struct pci_dev *pdev,
*
* Restart the card from scratch, as if from a cold-boot.
*/
-static pci_ers_result_t bf_pci_slot_reset(struct pci_dev *pdev)
-{
+static pci_ers_result_t bf_pci_slot_reset(struct pci_dev *pdev) {
/* nothing to do for now as we do not expect to get backto normal after
- * a pcie link reset
+ * a pcie link reset. Not expected to be invoked.
* TBD: fill in this function if tofino can recover after an error
*/
- return PCI_ERS_RESULT_DISCONNECT;
+ printk(KERN_ERR "BF pci_slot_reset invoked after pci error\n");
+ return PCI_ERS_RESULT_RECOVERED;
}
/**
@@ -1286,22 +1350,13 @@ static pci_ers_result_t bf_pci_slot_reset(struct pci_dev *pdev)
* This callback is called when the error recovery driver tells us that
* its OK to resume normal operation.
*/
-static void bf_pci_resume(struct pci_dev *pdev)
-{
- /* this function should never be called for Tofinoi */
- struct bf_pci_dev *bfdev = pci_get_drvdata(pdev);
-
+static void bf_pci_resume(struct pci_dev *pdev) {
printk(KERN_ERR "BF io_resume invoked after pci error\n");
- if (bfdev) {
- bfdev->info.pci_error_state = 0;
- }
}
-static int
-bf_config_intr_mode(char *intr_str)
-{
+static int bf_config_intr_mode(char *intr_str) {
if (!intr_str) {
- pr_info("Use MSIX interrupt by default\n");
+ pr_info("Use MSI interrupt by default\n");
return 0;
}
@@ -1314,67 +1369,108 @@ bf_config_intr_mode(char *intr_str)
} else if (!strcmp(intr_str, BF_INTR_MODE_LEGACY_NAME)) {
bf_intr_mode_default = BF_INTR_MODE_LEGACY;
pr_info("Use legacy interrupt\n");
- } else {
+ } else if (!strcmp(intr_str, BF_INTR_MODE_NONE_NAME)) {
bf_intr_mode_default = BF_INTR_MODE_NONE;
- pr_info(" No Interrupt \n");
+ pr_info("BF interrupt disabled\n");
+ } else {
+ pr_info("Error: bad intr_mode parameter - %s\n", intr_str);
+ return -EINVAL;
}
-
return 0;
}
static const struct pci_device_id bf_pci_tbl[] = {
- {PCI_VDEVICE(BF, TOFINO_DEV_ID_A0), 0},
- {PCI_VDEVICE(BF, TOFINO_DEV_ID_B0), 0},
- {PCI_VDEVICE(BF, TOFINO2_DEV_ID_A0), 0},
- /* required last entry */
- { .device = 0 }
-};
+ {PCI_VDEVICE(BF, TOFINO_DEV_ID_A0), 0},
+ {PCI_VDEVICE(BF, TOFINO_DEV_ID_B0), 0},
+ {PCI_VDEVICE(BF, TOFINO2_DEV_ID_A0), 0},
+ {PCI_VDEVICE(BF, TOFINO2_DEV_ID_A00), 0},
+ {PCI_VDEVICE(BF, TOFINO2_DEV_ID_B0), 0},
+ /* required last entry */
+ {.device = 0}};
/* PCI bus error handlers */
static struct pci_error_handlers bf_pci_err_handler = {
- .error_detected = bf_pci_error_detected,
- .slot_reset = bf_pci_slot_reset,
- .resume = bf_pci_resume,
+ .error_detected = bf_pci_error_detected,
+ .mmio_enabled = bf_pci_mmio_enabled,
+ .slot_reset = bf_pci_slot_reset,
+ .resume = bf_pci_resume,
};
-static struct pci_driver bf_pci_driver = {
- .name = "bf",
- .id_table = bf_pci_tbl,
- .probe = bf_pci_probe,
- .remove = bf_pci_remove,
- .err_handler = &bf_pci_err_handler
-};
+static struct pci_driver bf_pci_driver = {.name = "bf",
+ .id_table = bf_pci_tbl,
+ .probe = bf_pci_probe,
+ .remove = bf_pci_remove,
+ .err_handler = &bf_pci_err_handler};
-static int __init
-bfdrv_init(void)
-{
+static int __init bfdrv_init(void) {
int ret;
ret = bf_config_intr_mode(intr_mode);
- if (ret < 0)
+ /* do not enable DR interrupt if not using MSI or not in kpkt mode */
+ if ((bf_intr_mode_default != BF_INTR_MODE_MSI &&
+ bf_intr_mode_default != BF_INTR_MODE_LEGACY) || kpkt_mode == 0) {
+ kpkt_dr_int_en = 0;
+ }
+ if (kpkt_mode) {
+ printk(KERN_NOTICE "kpkt_mode %d hd_room %d dr_int_en %d rx_count %d\n",
+ kpkt_mode,
+ kpkt_hd_room,
+ kpkt_dr_int_en,
+ kpkt_rx_count);
+ }
+ if (ret < 0) {
return ret;
-
+ }
spin_lock_init(&bf_nonisr_lock);
return pci_register_driver(&bf_pci_driver);
}
-static void __exit
-bfdrv_exit(void)
-{
+static void __exit bfdrv_exit(void) {
pci_unregister_driver(&bf_pci_driver);
+ intr_mode = NULL;
+ kpkt_mode = 0;
}
module_init(bfdrv_init);
module_exit(bfdrv_exit);
+module_param(kpkt_mode, int, S_IRUGO);
+MODULE_PARM_DESC(kpkt_mode,
+ "bf kernel mode pkt processing (default=off):\n"
+ " 1 Use kernel mode bf_pkt processing\n"
+ " 0 Do not use kernel mode bf_pkt processing\n"
+ "\n");
+
+module_param(kpkt_hd_room, int, S_IRUGO);
+MODULE_PARM_DESC(kpkt_hd_room,
+ "head room to reserve when receiving packets (default=32):\n"
+ "\n");
+
+module_param(kpkt_rx_count, int, S_IRUGO);
+MODULE_PARM_DESC(kpkt_rx_count,
+ "number of buffers per rx pkt ring (default=256):\n"
+ "\n");
+/* dr_int_en is applicable only if MSI interrupt mode is selected */
+module_param(kpkt_dr_int_en, int, S_IRUGO);
+MODULE_PARM_DESC(kpkt_dr_int_en,
+ "bf pkt Interrupt enable (default=1):\n"
+ " 1 use interrupt\n"
+ " 0 Do not use interrupt\n"
+ "\n");
+
module_param(intr_mode, charp, S_IRUGO);
MODULE_PARM_DESC(intr_mode,
-"bf interrupt mode (default=msix):\n"
-" " BF_INTR_MODE_MSIX_NAME " Use MSIX interrupt\n"
-" " BF_INTR_MODE_MSI_NAME " Use MSI interrupt\n"
-" " BF_INTR_MODE_LEGACY_NAME " Use Legacy interrupt\n"
-"\n");
+ "bf interrupt mode (default=msix):\n"
+ " " BF_INTR_MODE_MSIX_NAME
+ " Use MSIX interrupt\n"
+ " " BF_INTR_MODE_MSI_NAME
+ " Use MSI interrupt\n"
+ " " BF_INTR_MODE_LEGACY_NAME
+ " Use Legacy interrupt\n"
+ " " BF_INTR_MODE_NONE_NAME
+ " Use no interrupt\n"
+ "\n");
MODULE_DEVICE_TABLE(pci, bf_pci_tbl);
MODULE_DESCRIPTION("Barefoot Tofino PCI device");
diff --git a/platform/barefoot/bfn-modules/modules/bf_kdrv.h b/platform/barefoot/bfn-modules/modules/bf_kdrv.h
new file mode 100644
index 000000000000..de5ca4bbc71c
--- /dev/null
+++ b/platform/barefoot/bfn-modules/modules/bf_kdrv.h
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ Barefoot Networks Switch ASIC Linux driver
+ Copyright(c) 2015 - 2019 Barefoot Networks, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ info@barefootnetworks.com
+ Barefoot Networks, 4750 Patrick Henry Drive, Santa Clara CA 95054
+
+*******************************************************************************/
+#ifndef _BF_KDRV_H_
+#define _BF_KDRV_H_
+
+#include
+#include
+#include
+
+#ifndef phys_addr_t
+typedef uint64_t phys_addr_t;
+#endif
+
+#define PCI_VENDOR_ID_BF 0x1d1c
+#define TOFINO_DEV_ID_A0 0x01
+#define TOFINO_DEV_ID_B0 0x10
+#define TOFINO2_DEV_ID_A0 0x0100
+#define TOFINO2_DEV_ID_A00 0x0000
+#define TOFINO2_DEV_ID_B0 0x0110
+
+#ifndef PCI_MSIX_ENTRY_SIZE
+#define PCI_MSIX_ENTRY_SIZE 16
+#define PCI_MSIX_ENTRY_LOWER_ADDR 0
+#define PCI_MSIX_ENTRY_UPPER_ADDR 4
+#define PCI_MSIX_ENTRY_DATA 8
+#define PCI_MSIX_ENTRY_VECTOR_CTRL 12
+#define PCI_MSIX_ENTRY_CTRL_MASKBIT 1
+#endif
+
+#define BF_CLASS_NAME "bf"
+#define BF_MAX_DEVICE_CNT 256
+#define BF_INTR_MODE_NONE_NAME "none"
+#define BF_INTR_MODE_LEGACY_NAME "legacy"
+#define BF_INTR_MODE_MSI_NAME "msi"
+#define BF_INTR_MODE_MSIX_NAME "msix"
+#define BF_MAX_BAR_MAPS 6
+#define BF_MSIX_ENTRY_CNT 32 /* 512 for tofino-1 */
+#define BF_MSI_ENTRY_CNT 2
+#define BF_MSI_INT_TBUS 1
+
+#define BF_TBUS_MSIX_INDEX_INVALID (0)
+#define BF_TBUS_MSIX_BASE_INDEX_TOF1 (32)
+
+/* Tofino generation type */
+typedef enum {
+ BF_TOFINO_NONE = 0,
+ BF_TOFINO_1,
+ BF_TOFINO_2,
+} bf_tof_type;
+
+/* device memory */
+struct bf_dev_mem {
+ const char *name;
+ phys_addr_t addr;
+ resource_size_t size;
+ void __iomem *internal_addr;
+};
+
+struct bf_listener {
+ struct bf_pci_dev *bfdev;
+ s32 event_count[BF_MSIX_ENTRY_CNT];
+ int minor;
+ struct bf_listener *next;
+};
+
+/* device information */
+struct bf_dev_info {
+ struct module *owner;
+ struct device *dev;
+ int minor;
+ atomic_t event[BF_MSIX_ENTRY_CNT];
+ wait_queue_head_t wait;
+ const char *version;
+ struct bf_dev_mem mem[BF_MAX_BAR_MAPS];
+ struct msix_entry *msix_entries;
+ long irq; /* first irq vector */
+ int num_irq; /* number of irq vectors */
+ unsigned long irq_flags; /* sharable ?? */
+ uint16_t pci_dev_id; /* generation type of BF ASIC */
+ bf_tof_type tof_type; /* Tofino generation type */
+ /* msix index assigned to tbus MSIX for Tofino-2 only */
+ int tbus_msix_ind[BF_TBUS_MSIX_INDICES_MAX];
+ int tbus_msix_map_enable;
+ int pci_error_state; /* was there a pci bus error */
+};
+
+/* cookie to be passed to IRQ handler, useful especially with MSIX */
+struct bf_int_vector {
+ struct bf_pci_dev *bf_dev;
+ int int_vec_offset;
+};
+
+/**
+ * A structure describing the private information for a BF pcie device.
+ */
+struct bf_pci_dev {
+ struct bf_dev_info info;
+ struct pci_dev *pdev;
+ enum bf_intr_mode mode;
+ u8 instance;
+ char name[16];
+ struct bf_int_vector bf_int_vec[BF_MSIX_ENTRY_CNT];
+ struct bf_listener *
+ listener_head; /* head of a singly linked list of listeners */
+ void *adapter_ptr; /* pkt processing adapter */
+};
+
+/* TBD: Need to build with CONFIG_PCI_MSI */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
+#if defined(RHEL_RELEASE_CODE)
+#else
+extern int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec);
+#endif /* defined(RHEL_RELEASE_CODE) */
+extern int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec);
+#else
+extern int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec);
+extern int pci_enable_msix_range(struct pci_dev *dev,
+ struct msix_entry *entries,
+ int minvec,
+ int maxvec);
+#endif
+
+#endif /* _BF_KDRV_H_ */
diff --git a/platform/barefoot/bfn-platform.mk b/platform/barefoot/bfn-platform.mk
index 854026b52949..1abbedffd6c6 100644
--- a/platform/barefoot/bfn-platform.mk
+++ b/platform/barefoot/bfn-platform.mk
@@ -1,5 +1,5 @@
-BFN_PLATFORM = bfnplatform_20191115_deb9.deb
-$(BFN_PLATFORM)_URL = "https://github.com/barefootnetworks/sonic-release-pkgs/raw/dev/bfnplatform_20191115_deb9.deb"
+BFN_PLATFORM = bfnplatform_20200407_deb9.deb
+$(BFN_PLATFORM)_URL = "https://github.com/barefootnetworks/sonic-release-pkgs/raw/dev/$(BFN_PLATFORM)"
SONIC_ONLINE_DEBS += $(BFN_PLATFORM)
$(BFN_SAI_DEV)_DEPENDS += $(BFN_PLATFORM)
diff --git a/platform/barefoot/bfn-sai.mk b/platform/barefoot/bfn-sai.mk
index 6f413d50c11e..b58cce6fcf47 100644
--- a/platform/barefoot/bfn-sai.mk
+++ b/platform/barefoot/bfn-sai.mk
@@ -1,5 +1,8 @@
-BFN_SAI = bfnsdk_20191115_deb9.deb
-$(BFN_SAI)_URL = "https://github.com/barefootnetworks/sonic-release-pkgs/raw/dev/bfnsdk_20191115_deb9.deb"
+BFN_SAI = bfnsdk_20200407_deb9.deb
+$(BFN_SAI)_URL = "https://github.com/barefootnetworks/sonic-release-pkgs/raw/dev/$(BFN_SAI)"
+
+$(BFN_SAI)_DEPENDS += $(LIBNL_GENL3_DEV)
+$(BFN_SAI)_RDEPENDS += $(LIBNL_GENL3)
SONIC_ONLINE_DEBS += $(BFN_SAI)
$(BFN_SAI_DEV)_DEPENDS += $(BFN_SAI)
diff --git a/platform/barefoot/docker-syncd-bfn-rpc.mk b/platform/barefoot/docker-syncd-bfn-rpc.mk
index d9cb0b5d6172..11b70a3a774f 100644
--- a/platform/barefoot/docker-syncd-bfn-rpc.mk
+++ b/platform/barefoot/docker-syncd-bfn-rpc.mk
@@ -2,7 +2,7 @@
DOCKER_SYNCD_BFN_RPC = docker-syncd-bfn-rpc.gz
$(DOCKER_SYNCD_BFN_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-bfn-rpc
-$(DOCKER_SYNCD_BFN_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT)
+$(DOCKER_SYNCD_BFN_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(PTF)
$(DOCKER_SYNCD_BFN_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)
ifeq ($(INSTALL_DEBUG_TOOLS), y)
$(DOCKER_SYNCD_BFN_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \
diff --git a/platform/barefoot/docker-syncd-bfn.mk b/platform/barefoot/docker-syncd-bfn.mk
index 6f3ed59ad285..3a5c693e2fa8 100644
--- a/platform/barefoot/docker-syncd-bfn.mk
+++ b/platform/barefoot/docker-syncd-bfn.mk
@@ -11,4 +11,4 @@ $(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \
$(LIBSAIREDIS_DBG)
$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /host/warmboot:/var/warmboot
-
+$(DOCKER_SYNCD_BASE)_BASE_IMAGE_FILES += monit_syncd:/etc/monit/conf.d
diff --git a/platform/barefoot/docker-syncd-bfn/base_image_files/monit_syncd b/platform/barefoot/docker-syncd-bfn/base_image_files/monit_syncd
new file mode 100644
index 000000000000..3079618990ed
--- /dev/null
+++ b/platform/barefoot/docker-syncd-bfn/base_image_files/monit_syncd
@@ -0,0 +1,7 @@
+###############################################################################
+## Monit configuration for syncd container
+## process list:
+## syncd
+###############################################################################
+check process syncd matching "/usr/bin/syncd"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/platform/barefoot/docker-syncd-bfn/supervisord.conf b/platform/barefoot/docker-syncd-bfn/supervisord.conf
index 1e015fef931f..1744d6ffefb5 100644
--- a/platform/barefoot/docker-syncd-bfn/supervisord.conf
+++ b/platform/barefoot/docker-syncd-bfn/supervisord.conf
@@ -3,6 +3,12 @@ logfile_maxbytes=1MB
logfile_backups=2
nodaemon=true
+[eventlistener:supervisor-proc-exit-listener]
+command=/usr/bin/supervisor-proc-exit-listener --container-name syncd
+events=PROCESS_STATE_EXITED
+autostart=true
+autorestart=unexpected
+
[program:start.sh]
command=/usr/bin/start.sh
priority=1
diff --git a/platform/barefoot/platform-modules-arista.mk b/platform/barefoot/platform-modules-arista.mk
index 480aa0cf8396..28c893b80713 100644
--- a/platform/barefoot/platform-modules-arista.mk
+++ b/platform/barefoot/platform-modules-arista.mk
@@ -7,7 +7,7 @@ export ARISTA_PLATFORM_MODULE_VERSION
ARISTA_PLATFORM_MODULE = sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_amd64.deb
$(ARISTA_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-arista
$(ARISTA_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON)
-SONIC_MAKE_DEBS += $(ARISTA_PLATFORM_MODULE)
+SONIC_DPKG_DEBS += $(ARISTA_PLATFORM_MODULE)
ARISTA_PLATFORM_MODULE_PYTHON2 = python-sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_all.deb
$(eval $(call add_extra_package,$(ARISTA_PLATFORM_MODULE),$(ARISTA_PLATFORM_MODULE_PYTHON2)))
diff --git a/platform/barefoot/sonic-platform-modules-arista b/platform/barefoot/sonic-platform-modules-arista
index 10750325b6cf..39860a109853 160000
--- a/platform/barefoot/sonic-platform-modules-arista
+++ b/platform/barefoot/sonic-platform-modules-arista
@@ -1 +1 @@
-Subproject commit 10750325b6cfc7a1dc1a8b0734008bde1bb3ac06
+Subproject commit 39860a109853b2f37367dfe68905e019b509d5bf
diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control
index 192da9dab95c..e3f5356f22db 100644
--- a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control
+++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control
@@ -7,6 +7,6 @@ Standards-Version: 3.9.3
Package: sonic-platform-modules-bfn-montara
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/control b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/control
index edbc5b890c58..bc6c990efebb 100644
--- a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/control
+++ b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/control
@@ -7,6 +7,6 @@ Standards-Version: 3.9.3
Package: sonic-platform-modules-bfn-newport
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel module for bfn platform fpga and scripts for the devices such as fan, led, sfp
diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/control b/platform/barefoot/sonic-platform-modules-bfn/debian/control
index 04d4c598e9d9..cca87831f1f1 100644
--- a/platform/barefoot/sonic-platform-modules-bfn/debian/control
+++ b/platform/barefoot/sonic-platform-modules-bfn/debian/control
@@ -7,6 +7,6 @@ Standards-Version: 3.9.3
Package: sonic-platform-modules-bfn
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/qsfp_monitor.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/qsfp_monitor.sh
index 249f179216a6..7776493bc20a 100755
--- a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/qsfp_monitor.sh
+++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/qsfp_monitor.sh
@@ -65,7 +65,7 @@ function _docker_swss_check {
while true
do
# Check if syncd starts
- result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME
+ result=`sonic-db-cli ASIC_DB HLEN HIDDEN`
if [ "$result" == "3" ]; then
return
fi
diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/qsfp_monitor.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/qsfp_monitor.sh
index 23a3fd066bee..9213d115f656 100755
--- a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/qsfp_monitor.sh
+++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/qsfp_monitor.sh
@@ -66,7 +66,7 @@ function _docker_swss_check {
while true
do
# Check if syncd starts
- result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME
+ result=`sonic-db-cli ASIC_DB HLEN HIDDEN`
if [ "$result" == "3" ]; then
return
fi
diff --git a/platform/broadcom/docker-syncd-brcm-rpc.mk b/platform/broadcom/docker-syncd-brcm-rpc.mk
index bd2ef01c5eed..355d7e0f1f8c 100644
--- a/platform/broadcom/docker-syncd-brcm-rpc.mk
+++ b/platform/broadcom/docker-syncd-brcm-rpc.mk
@@ -2,7 +2,7 @@
DOCKER_SYNCD_BRCM_RPC = docker-syncd-brcm-rpc.gz
$(DOCKER_SYNCD_BRCM_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-brcm-rpc
-$(DOCKER_SYNCD_BRCM_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT)
+$(DOCKER_SYNCD_BRCM_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(PTF)
ifeq ($(INSTALL_DEBUG_TOOLS), y)
$(DOCKER_SYNCD_BRCM_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \
$(LIBSWSSCOMMON_DBG) \
diff --git a/platform/broadcom/docker-syncd-brcm.mk b/platform/broadcom/docker-syncd-brcm.mk
index 29727dbb2260..d3a6d67c5cbc 100644
--- a/platform/broadcom/docker-syncd-brcm.mk
+++ b/platform/broadcom/docker-syncd-brcm.mk
@@ -16,3 +16,4 @@ $(DOCKER_SYNCD_BASE)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd
$(DOCKER_SYNCD_BASE)_BASE_IMAGE_FILES += bcmcmd:/usr/bin/bcmcmd
$(DOCKER_SYNCD_BASE)_BASE_IMAGE_FILES += bcmsh:/usr/bin/bcmsh
+$(DOCKER_SYNCD_BASE)_BASE_IMAGE_FILES += monit_syncd:/etc/monit/conf.d
diff --git a/platform/broadcom/docker-syncd-brcm/base_image_files/monit_syncd b/platform/broadcom/docker-syncd-brcm/base_image_files/monit_syncd
new file mode 100644
index 000000000000..0b9ec741cd57
--- /dev/null
+++ b/platform/broadcom/docker-syncd-brcm/base_image_files/monit_syncd
@@ -0,0 +1,11 @@
+###############################################################################
+## Monit configuration for syncd container
+## process list:
+## syncd
+## dsserve
+###############################################################################
+check process syncd matching "/usr/bin/syncd"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process dsserve matching "/usr/bin/dsserve /usr/bin/syncd"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/platform/broadcom/docker-syncd-brcm/supervisord.conf b/platform/broadcom/docker-syncd-brcm/supervisord.conf
index cd6712acbf22..3fa8febb85d8 100644
--- a/platform/broadcom/docker-syncd-brcm/supervisord.conf
+++ b/platform/broadcom/docker-syncd-brcm/supervisord.conf
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name syncd
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
diff --git a/platform/broadcom/platform-modules-arista.mk b/platform/broadcom/platform-modules-arista.mk
index 480aa0cf8396..28c893b80713 100644
--- a/platform/broadcom/platform-modules-arista.mk
+++ b/platform/broadcom/platform-modules-arista.mk
@@ -7,7 +7,7 @@ export ARISTA_PLATFORM_MODULE_VERSION
ARISTA_PLATFORM_MODULE = sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_amd64.deb
$(ARISTA_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-arista
$(ARISTA_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON)
-SONIC_MAKE_DEBS += $(ARISTA_PLATFORM_MODULE)
+SONIC_DPKG_DEBS += $(ARISTA_PLATFORM_MODULE)
ARISTA_PLATFORM_MODULE_PYTHON2 = python-sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_all.deb
$(eval $(call add_extra_package,$(ARISTA_PLATFORM_MODULE),$(ARISTA_PLATFORM_MODULE_PYTHON2)))
diff --git a/platform/broadcom/platform-modules-cel.mk b/platform/broadcom/platform-modules-cel.mk
index b7371e3282de..f36dae1073a0 100644
--- a/platform/broadcom/platform-modules-cel.mk
+++ b/platform/broadcom/platform-modules-cel.mk
@@ -3,10 +3,12 @@
CEL_DX010_PLATFORM_MODULE_VERSION = 0.9
CEL_HALIBURTON_PLATFORM_MODULE_VERSION = 0.9
CEL_SILVERSTONE_PLATFORM_MODULE_VERSION = 0.9
+CEL_SHAMU_PLATFORM_MODULE_VERSION = 0.9
export CEL_DX010_PLATFORM_MODULE_VERSION
export CEL_HALIBURTON_PLATFORM_MODULE_VERSION
export CEL_SILVERSTONE_PLATFORM_MODULE_VERSION
+export CEL_SHAMU_PLATFORM_MODULE_VERSION
CEL_DX010_PLATFORM_MODULE = platform-modules-dx010_$(CEL_DX010_PLATFORM_MODULE_VERSION)_amd64.deb
$(CEL_DX010_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-cel
@@ -14,12 +16,19 @@ $(CEL_DX010_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON)
$(CEL_DX010_PLATFORM_MODULE)_PLATFORM = x86_64-cel_seastone-r0
SONIC_DPKG_DEBS += $(CEL_DX010_PLATFORM_MODULE)
-CEL_HALIBURTON_PLATFORM_MODULE = platform-modules-haliburton_$(CEL_HALIBURTON_PLATFORM_MODULE_VERSION)_amd64.deb
-$(CEL_HALIBURTON_PLATFORM_MODULE)_PLATFORM = x86_64-cel_e1031-r0
-$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_HALIBURTON_PLATFORM_MODULE)))
-CEL_SILVERSTONE_PLATFORM_MODULE = platform-modules-silverstone_$(CEL_SILVERSTONE_PLATFORM_MODULE_VERSION)_amd64.deb
-$(CEL_SILVERSTONE_PLATFORM_MODULE)_PLATFORM = x86_64-cel_silverstone-r0
-$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_SILVERSTONE_PLATFORM_MODULE)))
+CEL_SHAMU_PLATFORM_MODULE = platform-modules-shamu_$(CEL_SHAMU_PLATFORM_MODULE_VERSION)_amd64.deb
+$(CEL_SHAMU_PLATFORM_MODULE)_PLATFORM = x86_64-alibaba_as14-40d-cl-r0
+$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_SHAMU_PLATFORM_MODULE)))
+
+#CEL_HALIBURTON_PLATFORM_MODULE = platform-modules-haliburton_$(CEL_HALIBURTON_PLATFORM_MODULE_VERSION)_amd64.deb
+#$(CEL_HALIBURTON_PLATFORM_MODULE)_PLATFORM = x86_64-cel_e1031-r0
+#$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_HALIBURTON_PLATFORM_MODULE)))
+
+#CEL_SILVERSTONE_PLATFORM_MODULE = platform-modules-silverstone_$(CEL_SILVERSTONE_PLATFORM_MODULE_VERSION)_amd64.deb
+#$(CEL_SILVERSTONE_PLATFORM_MODULE)_PLATFORM = x86_64-cel_silverstone-r0
+#$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_SILVERSTONE_PLATFORM_MODULE)))
+
+
SONIC_STRETCH_DEBS += $(CEL_DX010_PLATFORM_MODULE)
diff --git a/platform/broadcom/sai-modules.mk b/platform/broadcom/sai-modules.mk
index 1d559d0ad320..93132c2287bd 100644
--- a/platform/broadcom/sai-modules.mk
+++ b/platform/broadcom/sai-modules.mk
@@ -1,6 +1,6 @@
# Broadcom SAI modules
-KVERSION = 4.9.0-9-2-amd64
+KVERSION = 4.9.0-11-2-amd64
BRCM_OPENNSL_KERNEL_VERSION = 3.7.3.3-1
BRCM_OPENNSL_KERNEL = opennsl-modules_$(BRCM_OPENNSL_KERNEL_VERSION)_amd64.deb
diff --git a/platform/broadcom/sai.mk b/platform/broadcom/sai.mk
index 63c1e21ec7fc..e6e40039caf0 100644
--- a/platform/broadcom/sai.mk
+++ b/platform/broadcom/sai.mk
@@ -1,9 +1,8 @@
-BRCM_SAI = libsaibcm_3.7.3.3_amd64.deb
-$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.7/libsaibcm_3.7.3.3_amd64.deb?sv=2015-04-05&sr=b&sig=Y66VSRUEl4PDf5kHRo%2FS3DBBE9tONSyCzNJvi8IP9n8%3D&se=2033-08-25T01%3A22%3A08Z&sp=r"
-
-BRCM_SAI_DEV = libsaibcm-dev_3.7.3.3_amd64.deb
+BRCM_SAI = libsaibcm_3.7.3.3-4_amd64.deb
+$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.7/libsaibcm_3.7.3.3-4_amd64.deb?sv=2015-04-05&sr=b&sig=9z7vLhweD%2B%2FZylkr9XsDAJ3DdE5NJlcPTslFYyBuAXU%3D&se=2033-12-25T14%3A52%3A25Z&sp=r"
+BRCM_SAI_DEV = libsaibcm-dev_3.7.3.3-4_amd64.deb
$(eval $(call add_derived_package,$(BRCM_SAI),$(BRCM_SAI_DEV)))
-$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.7/libsaibcm-dev_3.7.3.3_amd64.deb?sv=2015-04-05&sr=b&sig=6%2BWzgFL845H9lKE0COsN53P4MO4UWfSo0z%2FmUMFbYVk%3D&se=2033-08-25T01%3A21%3A50Z&sp=r"
+$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.7/libsaibcm-dev_3.7.3.3-4_amd64.deb?sv=2015-04-05&sr=b&sig=SAOoGh2zdljiPuKeDoa%2B1lSJzZ8uXh2Irl2RZX1uAiA%3D&se=2033-12-25T14%3A53%3A44Z&sp=r"
SONIC_ONLINE_DEBS += $(BRCM_SAI)
-$(BRCM_SAI_DEV)_DEPENDS += $(BRCM_SAI)
\ No newline at end of file
+$(BRCM_SAI_DEV)_DEPENDS += $(BRCM_SAI)
diff --git a/platform/broadcom/saibcm-modules/debian/control b/platform/broadcom/saibcm-modules/debian/control
index 75b77c8a2f00..fafe7dfb9299 100644
--- a/platform/broadcom/saibcm-modules/debian/control
+++ b/platform/broadcom/saibcm-modules/debian/control
@@ -10,5 +10,5 @@ Standards-Version: 3.9.3
Package: opennsl-modules
Architecture: amd64
Section: main
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for broadcom SAI
diff --git a/platform/broadcom/saibcm-modules/debian/opennsl-modules.dirs b/platform/broadcom/saibcm-modules/debian/opennsl-modules.dirs
index 38af58a5c5ee..a32540eadcf5 100644
--- a/platform/broadcom/saibcm-modules/debian/opennsl-modules.dirs
+++ b/platform/broadcom/saibcm-modules/debian/opennsl-modules.dirs
@@ -1 +1 @@
-lib/modules/4.9.0-9-2-amd64/extra
+lib/modules/4.9.0-11-2-amd64/extra
diff --git a/platform/broadcom/saibcm-modules/debian/opennsl-modules.install b/platform/broadcom/saibcm-modules/debian/opennsl-modules.install
index e16980dc2c0d..9802d2f2443a 100644
--- a/platform/broadcom/saibcm-modules/debian/opennsl-modules.install
+++ b/platform/broadcom/saibcm-modules/debian/opennsl-modules.install
@@ -1,6 +1,6 @@
-systems/linux/user/x86-smp_generic_64-2_6/linux-bcm-knet.ko lib/modules/4.9.0-9-2-amd64/extra
-systems/linux/user/x86-smp_generic_64-2_6/linux-kernel-bde.ko lib/modules/4.9.0-9-2-amd64/extra
-systems/linux/user/x86-smp_generic_64-2_6/linux-user-bde.ko lib/modules/4.9.0-9-2-amd64/extra
-systems/linux/user/x86-smp_generic_64-2_6/linux-knet-cb.ko lib/modules/4.9.0-9-2-amd64/extra
-systems/linux/user/x86-smp_generic_64-2_6/psample.ko lib/modules/4.9.0-9-2-amd64/extra
+systems/linux/user/x86-smp_generic_64-2_6/linux-bcm-knet.ko lib/modules/4.9.0-11-2-amd64/extra
+systems/linux/user/x86-smp_generic_64-2_6/linux-kernel-bde.ko lib/modules/4.9.0-11-2-amd64/extra
+systems/linux/user/x86-smp_generic_64-2_6/linux-user-bde.ko lib/modules/4.9.0-11-2-amd64/extra
+systems/linux/user/x86-smp_generic_64-2_6/linux-knet-cb.ko lib/modules/4.9.0-11-2-amd64/extra
+systems/linux/user/x86-smp_generic_64-2_6/psample.ko lib/modules/4.9.0-11-2-amd64/extra
systemd/opennsl-modules.service lib/systemd/system
diff --git a/platform/broadcom/saibcm-modules/debian/rules b/platform/broadcom/saibcm-modules/debian/rules
index 0092cc1a1027..636874251aa9 100755
--- a/platform/broadcom/saibcm-modules/debian/rules
+++ b/platform/broadcom/saibcm-modules/debian/rules
@@ -60,7 +60,7 @@ kdist_config: prep-deb-files
kdist_clean: clean
dh_testdir
dh_clean
- SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 BUILD_PSAMPLE=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean
+ SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 BUILD_PSAMPLE=1 KERNDIR=/usr/src/linux-headers-4.9.0-11-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-11-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean
# rm -f driver/*.o driver/*.ko
#
### end KERNEL SETUP
@@ -78,7 +78,7 @@ build-arch-stamp:
dh_testdir
# Add here command to compile/build the package.
- SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 BUILD_PSAMPLE=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6
+ SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 BUILD_PSAMPLE=1 KERNDIR=/usr/src/linux-headers-4.9.0-11-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-11-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6
touch $@
@@ -103,7 +103,7 @@ clean:
rm -f build-arch-stamp build-indep-stamp configure-stamp
# Add here commands to clean up after the build process.
- SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 BUILD_PSAMPLE=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean
+ SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 BUILD_PSAMPLE=1 KERNDIR=/usr/src/linux-headers-4.9.0-11-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-11-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean
dh_clean
diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control
index 9a53b9823222..beba5b5f4e62 100644
--- a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control
+++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control
@@ -7,11 +7,11 @@ Standards-Version: 3.9.3
Package: sonic-platform-alphanetworks-snh60a0-320fv2
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: sonic-platform-alphanetworks-snh60b0-640f
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
diff --git a/platform/broadcom/sonic-platform-modules-arista b/platform/broadcom/sonic-platform-modules-arista
index 390d5e22f9c6..39860a109853 160000
--- a/platform/broadcom/sonic-platform-modules-arista
+++ b/platform/broadcom/sonic-platform-modules-arista
@@ -1 +1 @@
-Subproject commit 390d5e22f9c6c1a007ed325f6b0bd050a79aa5b1
+Subproject commit 39860a109853b2f37367dfe68905e019b509d5bf
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/control b/platform/broadcom/sonic-platform-modules-cel/debian/control
index 2e9b578872fa..009f5bbcc63b 100644
--- a/platform/broadcom/sonic-platform-modules-cel/debian/control
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/control
@@ -7,16 +7,22 @@ Standards-Version: 3.9.3
Package: platform-modules-dx010
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
-Package: platform-modules-haliburton
-Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
-Description: kernel modules for platform devices such as fan, led, sfp
+#Package: platform-modules-haliburton
+#Architecture: amd64
+#Depends: linux-image-4.9.0-11-2-amd64
+#Description: kernel modules for platform devices such as fan, led, sfp
+
+#Package: platform-modules-silverstone
+#Architecture: amd64
+#Depends: linux-image-4.9.0-11-2-amd64
+#Description: kernel modules for platform devices such as led, sfp.
-Package: platform-modules-silverstone
+
+Package: platform-modules-shamu
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
-Description: kernel modules for platform devices such as led, sfp.
+Depends: linux-image-4.9.0-11-2-amd64
+Description: kernel modules for platform devices such as fan, led, sfp
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install
index 2ab53302a9bf..8570fa1eae84 100644
--- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install
@@ -3,4 +3,3 @@ dx010/cfg/dx010-modules.conf etc/modules-load.d
dx010/systemd/platform-modules-dx010.service lib/systemd/system
dx010/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_seastone-r0
services/platform_api/platform_api_mgnt.sh usr/local/bin
-tools/afulnx_64 usr/local/bin
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.install
index d50306304cd5..df78b7a34ea4 100644
--- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.install
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.install
@@ -5,4 +5,3 @@ services/fancontrol/fancontrol.service lib/systemd/system
services/fancontrol/fancontrol usr/local/bin
haliburton/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_e1031-r0
services/platform_api/platform_api_mgnt.sh usr/local/bin
-tools/afulnx_64 usr/local/bin
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-jaws.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-jaws.init
new file mode 100644
index 000000000000..b8f079cf111b
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-jaws.init
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+### BEGIN INIT INFO
+# Provides: setup-board
+# Required-Start: $portmap
+# Required-Stop:
+# Should-Start:
+# Should-Stop:
+# Default-Start: S
+# Default-Stop: 0 6
+# Short-Description: Setup Jaws board.
+### END INIT INFO
+
+case "$1" in
+start)
+ echo -n "Setting up board... "
+
+ # Add driver to support HW
+ modprobe i2c-dev
+ modprobe dimm-bus
+ modprobe i2c-imc allow_unsafe_access=1
+ modprobe baseboard_cpld
+ modprobe switchboard_fpga
+ modprobe mc24lc64t
+
+ # Add driver to support TLV - EEPROM
+ echo 24lc64t 0x56 > /sys/bus/i2c/devices/i2c-0/new_device
+ echo "done."
+ ;;
+
+stop)
+ echo "done."
+ ;;
+
+force-reload|restart)
+ echo "Not supported"
+ ;;
+
+*)
+ echo "Usage: /etc/init.d/platform-modules-jaws.init {start|stop}"
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-jaws.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-jaws.install
new file mode 100644
index 000000000000..cdc1e9c0c255
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-jaws.install
@@ -0,0 +1,15 @@
+jaws/cfg/jaws-modules.conf etc/modules-load.d
+jaws/systemd/platform-modules-jaws.service lib/systemd/system
+tools/sync_bmc/bmc_vlan.service etc/systemd/system
+tools/sync_bmc/sync_bmc.service etc/systemd/system
+tools/sync_bmc/sync_bmc.timer etc/systemd/system
+tools/sync_bmc/bmc_vlan.sh /usr/local/etc/
+tools/sync_bmc/sync_bmc.py /usr/local/etc/
+tools/platformutil.py /usr/local/etc/
+tools/read_optic_temp.py /usr/local/etc/
+tools/bmcutil/bmcpwd /usr/local/etc/
+tools/bmcutil/bmcutil.py /usr/local/etc/
+tools/bmcutil/bmc-exec /usr/local/bin
+tools/bmc_wdt/bmc_wdt.service etc/systemd/system
+tools/bmc_wdt/bmc_wdt.py /usr/local/etc/
+tools/power_utils/power /usr/local/bin
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-jaws.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-jaws.postinst
new file mode 100644
index 000000000000..4dc1e15f3f9a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-jaws.postinst
@@ -0,0 +1,15 @@
+depmod -a
+
+# Enable bmc vlan_ip service
+systemctl enable bmc_vlan.service
+
+systemctl enable platform-modules-jaws.service
+systemctl start platform-modules-jaws.service
+
+# Enable platform-sync_bmc-timer
+# systemctl enable sync_bmc.timer
+# systemctl start sync_bmc.timer
+
+# Enable heartbeat timer
+systemctl enable bmc_wdt.service
+systemctl start bmc_wdt.service
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-shamu.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-shamu.init
new file mode 100644
index 000000000000..0bb69268b743
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-shamu.init
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+### BEGIN INIT INFO
+# Provides: setup-board
+# Required-Start: $portmap
+# Required-Stop:
+# Should-Start:
+# Should-Stop:
+# Default-Start: S
+# Default-Stop: 0 6
+# Short-Description: Setup Shamu board.
+### END INIT INFO
+
+case "$1" in
+start)
+ echo -n "Setting up board... "
+
+ # Add driver to support HW
+ modprobe dimm-bus
+ modprobe i2c-imc allow_unsafe_access=1
+ modprobe i2c-dev
+ modprobe baseboard_cpld
+ modprobe switchboard_fpga
+ modprobe mc24lc64t
+
+ # Add driver to support TLV - EEPROM
+ echo 24lc64t 0x56 > /sys/bus/i2c/devices/i2c-0/new_device
+ decode-syseeprom --init 2> /dev/null &
+
+ /bin/sh /usr/local/bin/platform_api_mgnt.sh init
+
+ echo 0x108 0xFF > /sys/devices/platform/AS1440D.switchboard/FPGA/setreg
+
+ echo "done."
+ ;;
+
+stop)
+ echo "done."
+ ;;
+
+force-reload|restart)
+ echo "Not supported"
+ ;;
+
+*)
+ echo "Usage: /etc/init.d/platform-modules-shamu.init {start|stop}"
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-shamu.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-shamu.install
new file mode 100644
index 000000000000..220e18165445
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-shamu.install
@@ -0,0 +1,20 @@
+shamu/scripts/sensors usr/bin
+shamu/scripts/platform_sensors.py usr/local/bin
+shamu/cfg/shamu-modules.conf etc/modules-load.d
+shamu/systemd/platform-modules-shamu.service lib/systemd/system
+shamu/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-alibaba_as14-40d-cl-r0
+services/platform_api/platform_api_mgnt.sh usr/local/bin
+
+tools/sync_bmc/bmc_vlan.service etc/systemd/system
+tools/sync_bmc/sync_bmc.service etc/systemd/system
+tools/sync_bmc/sync_bmc.timer etc/systemd/system
+tools/sync_bmc/bmc_vlan.sh /usr/local/etc/
+tools/sync_bmc/sync_bmc.py /usr/local/etc/
+tools/platformutil.py /usr/local/etc/
+tools/read_optic_temp.py /usr/local/etc/
+tools/bmcutil/bmcpwd /usr/local/etc/
+tools/bmcutil/bmcutil.py /usr/local/etc/
+tools/bmcutil/bmc-exec /usr/local/bin
+tools/bmc_wdt/bmc_wdt.service etc/systemd/system
+tools/bmc_wdt/bmc_wdt.py /usr/local/etc/
+tools/power_utils/power /usr/local/bin
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-shamu.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-shamu.postinst
new file mode 100644
index 000000000000..de84287b5b7f
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-shamu.postinst
@@ -0,0 +1,17 @@
+depmod -a
+
+# Enable bmc vlan_ip service
+systemctl enable bmc_vlan.service
+
+systemctl enable platform-modules-shamu.service
+systemctl start platform-modules-shamu.service
+
+/usr/local/bin/platform_api_mgnt.sh install
+
+# Enable platform-sync_bmc-timer
+# systemctl enable sync_bmc.timer
+# systemctl start sync_bmc.timer
+
+# Enable heartbeat timer
+systemctl enable bmc_wdt.service
+systemctl start bmc_wdt.service
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/rules b/platform/broadcom/sonic-platform-modules-cel/debian/rules
index dd5452ccaa11..5277c0b8ba76 100755
--- a/platform/broadcom/sonic-platform-modules-cel/debian/rules
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/rules
@@ -5,7 +5,10 @@ export INSTALL_MOD_DIR:=extra
KVERSION ?= $(shell uname -r)
KERNEL_SRC := /lib/modules/$(KVERSION)
MOD_SRC_DIR:= $(shell pwd)
-MODULE_DIRS:= dx010 haliburton silverstone
+MODULE_DIRS:= dx010 shamu
+# +++ add by maxwill to disable unneccessory pkg +++ #
+#MODULE_DIRS:= dx010 haliburton silverstone
+# --- add by maxwill to disable unneccessory pkg --- #
%:
dh $@
@@ -17,13 +20,21 @@ override_dh_auto_build:
python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \
cd $(MOD_SRC_DIR); \
done)
+ make -C $(MOD_SRC_DIR)/tools/ispvme_12.2;
+ gcc -std=c99 $(MOD_SRC_DIR)/tools/fpga_prog/fpga_prog.c -o $(MOD_SRC_DIR)/tools/fpga_prog/fpga_prog;
override_dh_auto_install:
(for mod in $(MODULE_DIRS); do \
dh_installdirs -pplatform-modules-$${mod} \
$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
+ dh_installdirs -pplatform-modules-$${mod} \
+ /usr/local/bin; \
cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \
debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
+ cp $(MOD_SRC_DIR)/tools/ispvme_12.2/ispvm \
+ debian/platform-modules-$${mod}/usr/local/bin/; \
+ cp $(MOD_SRC_DIR)/tools/fpga_prog/fpga_prog \
+ debian/platform-modules-$${mod}/usr/local/bin/; \
done)
override_dh_usrlocal:
@@ -33,4 +44,5 @@ override_dh_clean:
(for mod in $(MODULE_DIRS); do \
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \
done)
+ make -C $(MOD_SRC_DIR)/tools/ispvme_12.2 clean;
diff --git a/platform/broadcom/sonic-platform-modules-cel/jaws/cfg/jaws-modules.conf b/platform/broadcom/sonic-platform-modules-cel/jaws/cfg/jaws-modules.conf
new file mode 100644
index 000000000000..574c48f7a66f
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/jaws/cfg/jaws-modules.conf
@@ -0,0 +1,16 @@
+# /etc/modules: kernel modules to load at boot time.
+#
+# This file contains the names of kernel modules that should be loaded
+# at boot time, one per line. Lines beginning with "#" are ignored.
+
+i2c-i801
+i2c-isch
+i2c-ismt
+i2c-dev
+i2c-mux
+i2c-smbus
+
+i2c-mux-gpio
+i2c-mux-pca954x
+8021q
+
diff --git a/platform/broadcom/sonic-platform-modules-cel/jaws/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/Makefile
new file mode 100644
index 000000000000..f1777c8c5db9
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/Makefile
@@ -0,0 +1 @@
+obj-m := mc24lc64t.o baseboard_cpld.o switchboard_fpga.o i2c-imc.o dimm-bus.o
diff --git a/platform/broadcom/sonic-platform-modules-cel/jaws/modules/baseboard_cpld.c b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/baseboard_cpld.c
new file mode 100644
index 000000000000..951eb774a5f6
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/baseboard_cpld.c
@@ -0,0 +1,417 @@
+/*
+ * baseboard_cpld.c - The CPLD driver for the Base Board of Phalanxp
+ * The driver implement sysfs to access CPLD register on the baseboard of Phalanxp via LPC bus.
+ * Copyright (C) 2018 Celestica Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRIVER_NAME "AS14128H.cpldb"
+/**
+ * CPLD register address for read and write.
+ */
+#define VERSION_ADDR 0xA100
+#define SCRATCH_ADDR 0xA101
+#define SYS_LED_ADDR 0xA162
+
+#define CPLD_REGISTER_SIZE 0x7C
+
+struct cpld_b_data {
+ struct mutex cpld_lock;
+ uint16_t read_addr;
+};
+
+struct cpld_b_data *cpld_data;
+
+/**
+ * Read the value from scratch register as hex string.
+ * @param dev kernel device
+ * @param devattr kernel device attribute
+ * @param buf buffer for get value
+ * @return Hex string read from scratch register.
+ */
+
+
+static ssize_t scratch_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ unsigned char data = 0;
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SCRATCH_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return sprintf(buf,"0x%2.2x\n", data);
+}
+
+/**
+ * Set scratch register with specific hex string.
+ * @param dev kernel device
+ * @param devattr kernel device attribute
+ * @param buf buffer of set value
+ * @param count number of bytes in buffer
+ * @return number of bytes written, or error code < 0.
+ */
+static ssize_t scratch_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ char *last;
+
+ mutex_lock(&cpld_data->cpld_lock);
+ data = (uint16_t)strtoul(buf,&last,16);
+ if(data == 0 && buf == last){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+ outb(data, SCRATCH_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return count;
+}
+static DEVICE_ATTR_RW(scratch);
+
+
+/* CPLD version attributes */
+static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int len = 0;
+ // CPLD register is one byte
+ mutex_lock(&cpld_data->cpld_lock);
+ len = sprintf(buf, "0x%2.2x\n",inb(VERSION_ADDR));
+ mutex_unlock(&cpld_data->cpld_lock);
+ return len;
+}
+static DEVICE_ATTR_RO(version);
+
+
+static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ // CPLD register is one byte
+ uint16_t addr;
+ char *last;
+
+ addr = (uint16_t)strtoul(buf,&last,16);
+ if(addr == 0 && buf == last){
+ return -EINVAL;
+ }
+ cpld_data->read_addr = addr;
+ return count;
+}
+
+static ssize_t getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int len = 0;
+ // CPLD register is one byte
+ mutex_lock(&cpld_data->cpld_lock);
+ len = sprintf(buf, "0x%2.2x\n",inb(cpld_data->read_addr));
+ mutex_unlock(&cpld_data->cpld_lock);
+ return len;
+}
+static DEVICE_ATTR_RW(getreg);
+
+static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ // CPLD register is one byte
+ uint16_t addr;
+ uint8_t value;
+ char *tok;
+ char clone[count];
+ char *pclone = clone;
+ char *last;
+
+ strcpy(clone, buf);
+
+ mutex_lock(&cpld_data->cpld_lock);
+ tok = strsep((char**)&pclone, " ");
+ if(tok == NULL){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+ addr = (uint16_t)strtoul(tok,&last,16);
+ if(addr == 0 && tok == last){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+
+ tok = strsep((char**)&pclone, " ");
+ if(tok == NULL){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+ value = (uint8_t)strtoul(tok,&last,16);
+ if(value == 0 && tok == last){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+
+ outb(value,addr);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return count;
+}
+static DEVICE_ATTR_WO(setreg);
+
+/**
+ * Read all CPLD register in binary mode.
+ * @return number of byte read.
+ */
+static ssize_t dump_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t off, size_t count)
+{
+ unsigned long i=0;
+ ssize_t status;
+
+ mutex_lock(&cpld_data->cpld_lock);
+begin:
+ if(i < count){
+ buf[i++] = inb(VERSION_ADDR + off);
+ off++;
+ msleep(1);
+ goto begin;
+ }
+ status = count;
+
+ mutex_unlock(&cpld_data->cpld_lock);
+ return status;
+}
+static BIN_ATTR_RO(dump, CPLD_REGISTER_SIZE);
+
+/**
+ * Show system led status - on/off/1k/4k
+ * @param dev kernel device
+ * @param devattr kernel device attribute
+ * @param buf buffer for get value
+ * @return Hex string read from scratch register.
+ */
+static ssize_t sys_led_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ unsigned char data = 0;
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SYS_LED_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ data = data & 0x3;
+ return sprintf(buf, "%s\n",
+ data == 0x03 ? "off" : data == 0x02 ? "4k" : data ==0x01 ? "1k": "on");
+}
+
+/**
+ * Set the status of system led - on/off/1k/4k
+ * @param dev kernel device
+ * @param devattr kernel device attribute
+ * @param buf buffer of set value
+ * @param count number of bytes in buffer
+ * @return number of bytes written, or error code < 0.
+ */
+static ssize_t sys_led_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ unsigned char led_status,data;
+ if(sysfs_streq(buf, "off")){
+ led_status = 0x03;
+ }else if(sysfs_streq(buf, "4k")){
+ led_status = 0x02;
+ }else if(sysfs_streq(buf, "1k")){
+ led_status = 0x01;
+ }else if(sysfs_streq(buf, "on")){
+ led_status = 0x00;
+ }else{
+ count = -EINVAL;
+ return count;
+ }
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SYS_LED_ADDR);
+ data = data & ~(0x3);
+ data = data | led_status;
+ outb(data, SYS_LED_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return count;
+}
+static DEVICE_ATTR_RW(sys_led);
+
+/**
+ * Show system led color - both/green/yellow/none
+ * @param dev kernel device
+ * @param devattr kernel device attribute
+ * @param buf buffer for get value
+ * @return Hex string read from scratch register.
+ */
+static ssize_t sys_led_color_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ unsigned char data = 0;
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SYS_LED_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ data = (data >> 4) & 0x3;
+ return sprintf(buf, "%s\n",
+ data == 0x03 ? "off" : data == 0x02 ? "yellow" : data ==0x01 ? "green": "both");
+}
+
+/**
+ * Set the color of system led - both/green/yellow/none
+ * When both color is selected, only blink 1K or 4K is supported.
+ *
+ * @param dev kernel device
+ * @param devattr kernel device attribute
+ * @param buf buffer of set value
+ * @param count number of bytes in buffer
+ * @return number of bytes written, or error code < 0.
+ */
+static ssize_t sys_led_color_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ unsigned char led_status,data;
+ if(sysfs_streq(buf, "off")){
+ led_status = 0x03;
+ }else if(sysfs_streq(buf, "yellow")){
+ led_status = 0x02;
+ }else if(sysfs_streq(buf, "green")){
+ led_status = 0x01;
+ }else if(sysfs_streq(buf, "both")){
+ led_status = 0x00;
+ }else{
+ count = -EINVAL;
+ return count;
+ }
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SYS_LED_ADDR);
+ data = data & ~( 0x3 << 4);
+ data = data | (led_status << 4);
+ outb(data, SYS_LED_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return count;
+}
+static DEVICE_ATTR_RW(sys_led_color);
+
+static struct attribute *cpld_b_attrs[] = {
+ &dev_attr_version.attr,
+ &dev_attr_scratch.attr,
+ &dev_attr_getreg.attr,
+ &dev_attr_setreg.attr,
+ &dev_attr_sys_led.attr,
+ &dev_attr_sys_led_color.attr,
+ NULL,
+};
+
+static struct bin_attribute *cpld_b_bin_attrs[] = {
+ &bin_attr_dump,
+ NULL,
+};
+
+static struct attribute_group cpld_b_attrs_grp = {
+ .attrs = cpld_b_attrs,
+ .bin_attrs = cpld_b_bin_attrs,
+};
+
+static struct resource cpld_b_resources[] = {
+ {
+ .start = 0xA100,
+ .end = 0xA175,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static void cpld_b_dev_release( struct device * dev)
+{
+ return;
+}
+
+static struct platform_device cpld_b_dev = {
+ .name = DRIVER_NAME,
+ .id = -1,
+ .num_resources = ARRAY_SIZE(cpld_b_resources),
+ .resource = cpld_b_resources,
+ .dev = {
+ .release = cpld_b_dev_release,
+ }
+};
+
+static int cpld_b_drv_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int err = 0;
+
+ cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct cpld_b_data),
+ GFP_KERNEL);
+ if (!cpld_data)
+ return -ENOMEM;
+
+ mutex_init(&cpld_data->cpld_lock);
+
+ cpld_data->read_addr = VERSION_ADDR;
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (unlikely(!res)) {
+ printk(KERN_ERR "Specified Resource Not Available...\n");
+ return -ENODEV;
+ }
+
+ err = sysfs_create_group(&pdev->dev.kobj, &cpld_b_attrs_grp);
+ if (err) {
+ printk(KERN_ERR "Cannot create sysfs for baseboard CPLD\n");
+ return err;
+ }
+ return 0;
+}
+
+static int cpld_b_drv_remove(struct platform_device *pdev)
+{
+ sysfs_remove_group(&pdev->dev.kobj, &cpld_b_attrs_grp);
+ return 0;
+}
+
+static struct platform_driver cpld_b_drv = {
+ .probe = cpld_b_drv_probe,
+ .remove = __exit_p(cpld_b_drv_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+};
+
+int cpld_b_init(void)
+{
+ // Register platform device and platform driver
+ platform_device_register(&cpld_b_dev);
+ platform_driver_register(&cpld_b_drv);
+ return 0;
+}
+
+void cpld_b_exit(void)
+{
+ // Unregister platform device and platform driver
+ platform_driver_unregister(&cpld_b_drv);
+ platform_device_unregister(&cpld_b_dev);
+}
+
+module_init(cpld_b_init);
+module_exit(cpld_b_exit);
+
+
+MODULE_AUTHOR("Pradchaya P. ");
+MODULE_DESCRIPTION("Celestica Phalanxp CPLD baseboard driver");
+MODULE_VERSION("0.0.2");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-cel/jaws/modules/dimm-bus.c b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/dimm-bus.c
new file mode 100644
index 000000000000..9f30945e1d1c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/dimm-bus.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013-2016 Andrew Lutomirski
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include
+#include
+#include
+#include "dimm-bus.h"
+static bool probe_addr(struct i2c_adapter *adapter, int addr)
+{
+ /*
+ * So far, all known devices that live on DIMMs can be safely
+ * and reliably detected by trying to read a byte at address
+ * zero. (The exception is the SPD write protection control,
+ * which can't be probed and requires special hardware and/or
+ * quick writes to access, and has no driver.)
+ */
+ union i2c_smbus_data dummy;
+ return i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_READ, 0,
+ I2C_SMBUS_BYTE_DATA, &dummy) >= 0;
+}
+/**
+ * i2c_scan_dimm_bus() - Scans an SMBUS segment known to contain DIMMs
+ * @adapter: The SMBUS adapter to scan
+ *
+ * This function tells the DIMM-bus code that the adapter is known to
+ * contain DIMMs. i2c_scan_dimm_bus will probe for devices known to
+ * live on DIMMs.
+ *
+ * Do NOT call this function on general-purpose system SMBUS segments
+ * unless you know that the only things on the bus are DIMMs.
+ * Otherwise is it very likely to mis-identify other things on the
+ * bus.
+ *
+ * Callers are advised not to set adapter->class = I2C_CLASS_SPD to
+ * avoid having two separate mechanisms trying to automatically claim
+ * devices on the bus.
+ */
+void i2c_scan_dimm_bus(struct i2c_adapter *adapter)
+{
+ struct i2c_board_info info = {};
+ int slot;
+ /*
+ * We probe with "read byte data". If any DIMM SMBUS driver can't
+ * support that access type, this function should be updated.
+ */
+ if (WARN_ON(!i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_READ_BYTE_DATA)))
+ return;
+ /*
+ * Addresses on DIMMs use the three low bits to identify the slot
+ * and the four high bits to identify the device type. Known
+ * devices include:
+ *
+ * - 0x10 - 0x17: NVDIMM controller (pre-standard)
+ * - 0x18 - 0x1f: TSOD (Temperature Sensor on DIMM)
+ * - 0x40 - 0x47: JESD245 Byte Addressable Energy Backed Interface
+ * - 0x50 - 0x57: SPD (Serial Presence Detect) EEPROM
+ * - 0x30 - 0x37: SPD WP control -- not easy to probe
+ *
+ * There's no point in trying to probe the SPD WP control: we'd
+ * want to probe using quick reads, which i2c-imc doesn't
+ * support, we don't have a driver for it, we can't really use
+ * it without special hardware (it's not a normal i2c slave --
+ * see the JEDEC docs), and using it risks bricking the DIMM
+ * it's on anyway.
+ *
+ * NB: There's no need to save the return value from
+ * i2c_new_device, as the core code will unregister it for us
+ * when the adapter is removed. If users want to bind a
+ * different driver, nothing stops them from unbinding the
+ * drivers we request here.
+ */
+ for (slot = 0; slot < 8; slot++) {
+ /* If there's no SPD, then assume there's no DIMM here. */
+ if (!probe_addr(adapter, 0x50 | slot))
+ continue;
+ strcpy(info.type, "ee1004");
+ info.addr = 0x50 | slot;
+ i2c_new_device(adapter, &info);
+ if (probe_addr(adapter, 0x18 | slot)) {
+ /*
+ * This is a temperature sensor. The interface is
+ * defined in the JEDEC TSE2004av specification.
+ * Linux's driver for this is called "jc42", which
+ * is a bit nonsensical (JC-42 is the name of the
+ * committee, not the sensor).
+ */
+ strcpy(info.type, "jc42");
+ info.addr = 0x18 | slot;
+ i2c_new_device(adapter, &info);
+ }
+ }
+}
+EXPORT_SYMBOL(i2c_scan_dimm_bus);
+MODULE_AUTHOR("Andrew Lutomirski ");
+MODULE_DESCRIPTION("i2c DIMM bus support");
+MODULE_LICENSE("GPL v2");
+
diff --git a/platform/broadcom/sonic-platform-modules-cel/jaws/modules/dimm-bus.h b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/dimm-bus.h
new file mode 100644
index 000000000000..8f14d5fb973f
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/dimm-bus.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2013-2016 Andrew Lutomirski
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef _I2C_DIMM_BUS
+#define _I2C_DIMM_BUS
+struct i2c_adapter;
+void i2c_scan_dimm_bus(struct i2c_adapter *adapter);
+#endif /* _I2C_DIMM_BUS */
+
diff --git a/platform/broadcom/sonic-platform-modules-cel/jaws/modules/i2c-imc.c b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/i2c-imc.c
new file mode 100644
index 000000000000..7b053f43916e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/i2c-imc.c
@@ -0,0 +1,556 @@
+/*
+ * Copyright (c) 2013-2016 Andrew Lutomirski
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "dimm-bus.h"
+
+/*
+ * The datasheet can be found here, for example:
+ * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e5-1600-2600-vol-2-datasheet.pdf
+ *
+ * There seem to be quite a few bugs or spec errors, though:
+ *
+ * - A successful transaction sets WOD and RDO.
+ *
+ * - The docs for TSOD_POLL_EN make no sense (see imc_channel_claim).
+ *
+ * - Erratum BT109, which says:
+ *
+ * The processor may not complete SMBus (System Management Bus)
+ * transactions targeting the TSOD (Temperature Sensor On DIMM)
+ * when Package C-States are enabled. Due to this erratum, if the
+ * processor transitions into a Package C-State while an SMBus
+ * transaction with the TSOD is in process, the processor will
+ * suspend receipt of the transaction. The transaction completes
+ * while the processor is in a Package C-State. Upon exiting
+ * Package C-State, the processor will attempt to resume the
+ * SMBus transaction, detect a protocol violation, and log an
+ * error.
+ *
+ * The description notwithstanding, I've seen difficult-to-reproduce
+ * issues when the system goes completely idle (so package C-states can
+ * be entered) while software-initiated SMBUS transactions are in
+ * progress.
+ */
+
+/* Register offsets (in PCI configuration space) */
+#define SMBSTAT(i) (0x180 + 0x10*(i))
+#define SMBCMD(i) (0x184 + 0x10*(i))
+#define SMBCNTL(i) (0x188 + 0x10*(i))
+#define SMB_TSOD_POLL_RATE_CNTR(i) (0x18C + 0x10*(i))
+#define SMB_TSOD_POLL_RATE (0x1A8)
+
+/* SMBSTAT fields */
+#define SMBSTAT_RDO (1U << 31) /* Read Data Valid */
+#define SMBSTAT_WOD (1U << 30) /* Write Operation Done */
+#define SMBSTAT_SBE (1U << 29) /* SMBus Error */
+#define SMBSTAT_SMB_BUSY (1U << 28) /* SMBus Busy State */
+/* 26:24 is the last automatically polled TSOD address */
+#define SMBSTAT_RDATA_MASK 0xffff /* result of a read */
+
+/* SMBCMD fields */
+#define SMBCMD_TRIGGER (1U << 31) /* CMD Trigger */
+#define SMBCMD_PNTR_SEL (1U << 30) /* HW polls TSOD with pointer */
+#define SMBCMD_WORD_ACCESS (1U << 29) /* word (vs byte) access */
+#define SMBCMD_TYPE_MASK (3U << 27) /* Mask for access type */
+#define SMBCMD_TYPE_READ (0U << 27) /* Read */
+#define SMBCMD_TYPE_WRITE (1U << 27) /* Write */
+#define SMBCMD_TYPE_PNTR_WRITE (3U << 27) /* Write to pointer */
+#define SMBCMD_SA_MASK (7U << 24) /* Slave Address high bits */
+#define SMBCMD_SA_SHIFT 24
+#define SMBCMD_BA_MASK 0xff0000 /* Bus Txn address */
+#define SMBCMD_BA_SHIFT 16
+#define SMBCMD_WDATA_MASK 0xffff /* data to write */
+
+/* SMBCNTL fields */
+#define SMBCNTL_DTI_MASK 0xf0000000 /* Slave Address low bits */
+#define SMBCNTL_DTI_SHIFT 28 /* Slave Address low bits */
+#define SMBCNTL_CKOVRD (1U << 27) /* # Clock Override */
+#define SMBCNTL_DIS_WRT (1U << 26) /* Disable Write (sadly) */
+#define SMBCNTL_SOFT_RST (1U << 10) /* Soft Reset */
+#define SMBCNTL_TSOD_POLL_EN (1U << 8) /* TSOD Polling Enable */
+/* Bits 0-3 and 4-6 indicate TSOD presence in various slots */
+
+/* Bits that might randomly change if we race with something. */
+#define SMBCMD_OUR_BITS (~(u32)SMBCMD_TRIGGER)
+#define SMBCNTL_OUR_BITS (SMBCNTL_DTI_MASK | SMBCNTL_TSOD_POLL_EN)
+
+/* System Address Controller, PCI dev 13 fn 6, 8086.3cf5 */
+#define SAD_CONTROL 0xf4
+
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_BR 0x3cf5 /* 13.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA 0x3ca8 /* 15.0 */
+
+#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA 0x6fa8
+#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM 0x6f71
+#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA 0x6f68
+#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM 0x6f79
+
+static atomic_t imc_raced; /* Set permanently to 1 if we screw up. */
+
+static bool allow_unsafe_access;
+
+struct imc_channel {
+ struct i2c_adapter adapter;
+ struct mutex mutex; /* protects access to regs and prev_tsod_poll */
+ bool can_write, suspended;
+ bool prev_tsod_poll;
+};
+
+struct imc_priv {
+ struct pci_dev *pci_dev;
+ struct imc_channel channels[2];
+};
+
+static bool imc_wait_not_busy(struct imc_priv *priv, int chan, u32 *stat)
+{
+ /*
+ * The clock is around 100kHz, and transactions are nine cycles
+ * per byte plus a few start/stop cycles, plus whatever clock
+ * streching is involved. This means that polling every 70us
+ * or so will give decent performance.
+ *
+ * Ideally we would calculate a good estimate for the
+ * transaction time and sleep, but busy-waiting is an effective
+ * workaround for an apparent Sandy Bridge bug that causes bogus
+ * output if the system enters a package C-state. (NB: these
+ * states are systemwide -- we don't need be running on the
+ * right package for this to work.)
+ *
+ * When Ivy Bridge and Haswell support are added, we could
+ * consider making the busy-wait depend on the platform.
+ */
+
+ int i;
+
+ for (i = 0; i < 50; i++) {
+ pci_read_config_dword(priv->pci_dev, SMBSTAT(chan), stat);
+ if (!(*stat & SMBSTAT_SMB_BUSY))
+ return true;
+ udelay(70); /* see comment above -- we need to busy-wait */
+ }
+
+ return false;
+}
+
+static void imc_channel_release(struct imc_priv *priv, int chan)
+{
+ /* Return to HW control. */
+ if (priv->channels[chan].prev_tsod_poll) {
+ u32 cntl;
+
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+ cntl |= SMBCNTL_TSOD_POLL_EN;
+ pci_write_config_dword(priv->pci_dev, SMBCNTL(chan), cntl);
+ }
+}
+
+static int imc_channel_claim(struct imc_priv *priv, int chan)
+{
+ /*
+ * The docs are a bit confused here. We're supposed to disable TSOD
+ * polling, then wait for busy to be cleared, then set
+ * SMBCNTL_TSOD_POLL_EN to zero to switch to software control. But
+ * SMBCNTL_TSOD_POLL_EN is the only documented way to turn off polling.
+ */
+
+ u32 cntl, stat;
+
+ if (priv->channels[chan].suspended)
+ return -EIO;
+
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+ priv->channels[chan].prev_tsod_poll = !!(cntl & SMBCNTL_TSOD_POLL_EN);
+ cntl &= ~SMBCNTL_TSOD_POLL_EN;
+ pci_write_config_dword(priv->pci_dev, SMBCNTL(chan), cntl);
+
+ /* Sometimes the hardware won't let go. */
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+ if (cntl & SMBCNTL_TSOD_POLL_EN)
+ return -EBUSY;
+
+ if (!imc_wait_not_busy(priv, chan, &stat)) {
+ imc_channel_release(priv, chan);
+ return -EBUSY; /* Someone else is controlling the bus. */
+ }
+
+ return 0; /* The channel is ours. */
+}
+
+static bool imc_channel_can_claim(struct imc_priv *priv, int chan)
+{
+ u32 orig_cntl, cntl;
+
+ /* See if we can turn off TSOD_POLL_EN. */
+
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &orig_cntl);
+ pci_write_config_dword(priv->pci_dev, SMBCNTL(chan),
+ orig_cntl & ~SMBCNTL_TSOD_POLL_EN);
+
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+ if (cntl & SMBCNTL_TSOD_POLL_EN)
+ return false; /* Failed. */
+
+ pci_write_config_dword(priv->pci_dev, SMBCNTL(chan), orig_cntl);
+ return true;
+}
+
+/*
+ * The iMC supports five access types. The terminology is rather
+ * inconsistent. These are the types:
+ *
+ * "Write to pointer register SMBus": I2C_SMBUS_WRITE, I2C_SMBUS_BYTE
+ *
+ * Read byte/word: I2C_SMBUS_READ, I2C_SMBUS_{BYTE|WORD}_DATA
+ *
+ * Write byte/word: I2C_SMBUS_WRITE, I2C_SMBUS_{BYTE|WORD}_DATA
+ *
+ * The pointer write operations is AFAICT completely useless for
+ * software control, for two reasons. First, HW periodically polls any
+ * TSODs on the bus, so it will corrupt the pointer in between SW
+ * transactions. More importantly, the matching "read byte"/"receive
+ * byte" (the address-less single-byte read) is not available for SW
+ * control. Therefore, this driver doesn't implement pointer writes
+ *
+ * There is no PEC support.
+ */
+
+static u32 imc_func(struct i2c_adapter *adapter)
+{
+ int chan;
+ struct imc_channel *ch;
+ struct imc_priv *priv = i2c_get_adapdata(adapter);
+
+ chan = (adapter == &priv->channels[0].adapter ? 0 : 1);
+ ch = &priv->channels[chan];
+
+ if (ch->can_write)
+ return I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
+ else
+ return I2C_FUNC_SMBUS_READ_BYTE_DATA |
+ I2C_FUNC_SMBUS_READ_WORD_DATA;
+}
+
+static s32 imc_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+ unsigned short flags, char read_write, u8 command,
+ int size, union i2c_smbus_data *data)
+{
+ int ret, chan;
+ u32 cmd = 0, cntl, final_cmd, final_cntl, stat;
+ struct imc_channel *ch;
+ struct imc_priv *priv = i2c_get_adapdata(adap);
+
+ if (atomic_read(&imc_raced))
+ return -EIO; /* Minimize damage. */
+
+ chan = (adap == &priv->channels[0].adapter ? 0 : 1);
+ ch = &priv->channels[chan];
+
+ /* Encode CMD part of addresses and access size */
+ cmd |= ((u32)addr & 0x7) << SMBCMD_SA_SHIFT;
+ cmd |= ((u32)command) << SMBCMD_BA_SHIFT;
+ if (size == I2C_SMBUS_WORD_DATA)
+ cmd |= SMBCMD_WORD_ACCESS;
+
+ /* Encode read/write and data to write */
+ if (read_write == I2C_SMBUS_READ) {
+ cmd |= SMBCMD_TYPE_READ;
+ } else {
+ cmd |= SMBCMD_TYPE_WRITE;
+ cmd |= (size == I2C_SMBUS_WORD_DATA
+ ? swab16(data->word)
+ : data->byte);
+ }
+
+ mutex_lock(&ch->mutex);
+
+ ret = imc_channel_claim(priv, chan);
+ if (ret)
+ goto out_unlock;
+
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+ cntl &= ~SMBCNTL_DTI_MASK;
+ cntl |= ((u32)addr >> 3) << SMBCNTL_DTI_SHIFT;
+ pci_write_config_dword(priv->pci_dev, SMBCNTL(chan), cntl);
+
+ /*
+ * This clears SMBCMD_PNTR_SEL. We leave it cleared so that we don't
+ * need to think about keeping the TSOD pointer state consistent with
+ * the hardware's expectation. This probably has some miniscule
+ * power cost, as TSOD polls will take 9 extra cycles.
+ */
+ cmd |= SMBCMD_TRIGGER;
+ pci_write_config_dword(priv->pci_dev, SMBCMD(chan), cmd);
+
+ if (!imc_wait_not_busy(priv, chan, &stat)) {
+ /* Timeout. TODO: Reset the controller? */
+ ret = -ETIMEDOUT;
+ dev_dbg(&priv->pci_dev->dev, "controller is wedged\n");
+ goto out_release;
+ }
+
+ /*
+ * Be paranoid: try to detect races. This will only detect races
+ * against BIOS, not against hardware. (I've never seen this happen.)
+ */
+ pci_read_config_dword(priv->pci_dev, SMBCMD(chan), &final_cmd);
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &final_cntl);
+ if (((cmd ^ final_cmd) & SMBCMD_OUR_BITS) ||
+ ((cntl ^ final_cntl) & SMBCNTL_OUR_BITS)) {
+ WARN(1, "iMC SMBUS raced against firmware");
+ dev_err(&priv->pci_dev->dev,
+ "Access to channel %d raced: cmd 0x%08X->0x%08X, cntl 0x%08X->0x%08X\n",
+ chan, cmd, final_cmd, cntl, final_cntl);
+ atomic_set(&imc_raced, 1);
+ ret = -EIO;
+ goto out_release;
+ }
+
+ if (stat & SMBSTAT_SBE) {
+ /*
+ * Clear the error to re-enable TSOD polling. The docs say
+ * that, as long as SBE is set, TSOD polling won't happen.
+ * The docs also say that writing zero to this bit (which is
+ * the only writable bit in the whole register) will clear
+ * the error. Empirically, writing 0 does not clear SBE, but
+ * it's probably still good to do the write in compliance with
+ * the spec. (TSOD polling still happens and seems to
+ * clear SBE on its own.)
+ */
+ pci_write_config_dword(priv->pci_dev, SMBSTAT(chan), 0);
+ ret = -ENXIO;
+ goto out_release;
+ }
+
+ if (read_write == I2C_SMBUS_READ) {
+ if (!(stat & SMBSTAT_RDO)) {
+ dev_dbg(&priv->pci_dev->dev,
+ "Unexpected read status 0x%08X\n", stat);
+ ret = -EIO;
+ goto out_release;
+ }
+
+ /*
+ * The iMC SMBUS controller thinks of SMBUS words as
+ * being big-endian (MSB first). Linux treats them as
+ * little-endian, so we need to swap them.
+ *
+ * Note: the controller will often (always?) set WOD
+ * here. This is probably a hardware bug.
+ */
+ if (size == I2C_SMBUS_WORD_DATA)
+ data->word = swab16(stat & SMBSTAT_RDATA_MASK);
+ else
+ data->byte = stat & 0xFF;
+ } else {
+ /*
+ * Note: the controller will often (always?) set RDO here.
+ * This is probably a hardware bug.
+ */
+ if (!(stat & SMBSTAT_WOD)) {
+ dev_dbg(&priv->pci_dev->dev,
+ "Unexpected write status 0x%08X\n", stat);
+ ret = -EIO;
+ }
+ }
+
+out_release:
+ imc_channel_release(priv, chan);
+
+out_unlock:
+ mutex_unlock(&ch->mutex);
+
+ return ret;
+}
+
+static const struct i2c_algorithm imc_smbus_algorithm = {
+ .smbus_xfer = imc_smbus_xfer,
+ .functionality = imc_func,
+};
+
+static int imc_init_channel(struct imc_priv *priv, int i, int socket)
+{
+ int err;
+ u32 val;
+ struct imc_channel *ch = &priv->channels[i];
+
+ /*
+ * With CLTT enabled, the hardware won't let us turn
+ * off TSOD polling. The device is completely useless
+ * when this happens (at least without help from Intel),
+ * but we can at least minimize confusion.
+ */
+ if (!imc_channel_can_claim(priv, i)) {
+ dev_warn(&priv->pci_dev->dev,
+ "iMC channel %d: we cannot control the HW. Is CLTT on?\n",
+ i);
+ return -EBUSY;
+ }
+
+ i2c_set_adapdata(&ch->adapter, priv);
+ ch->adapter.owner = THIS_MODULE;
+ ch->adapter.algo = &imc_smbus_algorithm;
+ ch->adapter.dev.parent = &priv->pci_dev->dev;
+
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(i), &val);
+ ch->can_write = !(val & SMBCNTL_DIS_WRT);
+
+ mutex_init(&ch->mutex);
+
+ snprintf(ch->adapter.name, sizeof(ch->adapter.name),
+ "iMC socket %d channel %d", socket, i);
+ err = i2c_add_adapter(&ch->adapter);
+ if (err) {
+ mutex_destroy(&ch->mutex);
+ return err;
+ }
+
+ i2c_scan_dimm_bus(&ch->adapter);
+
+ return 0;
+}
+
+static void imc_free_channel(struct imc_priv *priv, int i)
+{
+ struct imc_channel *ch = &priv->channels[i];
+
+ i2c_del_adapter(&ch->adapter);
+ mutex_destroy(&ch->mutex);
+}
+
+static struct pci_dev *imc_get_related_device(struct pci_bus *bus,
+ unsigned int devfn, u16 devid)
+{
+ struct pci_dev *dev = pci_get_slot(bus, devfn);
+
+ if (!dev)
+ return NULL;
+ if (dev->vendor != PCI_VENDOR_ID_INTEL || dev->device != devid) {
+ pci_dev_put(dev);
+ return NULL;
+ }
+ return dev;
+}
+
+static int imc_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ int i, j, err;
+ struct imc_priv *priv;
+
+ priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ priv->pci_dev = dev;
+
+ pci_set_drvdata(dev, priv);
+
+ for (i = 0; i < 1; i++) {
+ err = imc_init_channel(priv, i, 0);
+ if (err)
+ goto exit_free_channels;
+ printk(KERN_INFO "IMC: Create IMC SMBus OK.\n");
+ }
+
+ return 0;
+
+exit_free_channels:
+ printk(KERN_INFO "IMC: Free chennel I2C.\n");
+ for (j = 0; j < i; j++)
+ imc_free_channel(priv, j);
+ return err;
+}
+
+static void imc_remove(struct pci_dev *dev)
+{
+ int i;
+ struct imc_priv *priv = pci_get_drvdata(dev);
+
+ for (i = 0; i < 1; i++)
+ imc_free_channel(priv, i);
+}
+
+static int imc_suspend(struct pci_dev *dev, pm_message_t mesg)
+{
+ int i;
+ struct imc_priv *priv = pci_get_drvdata(dev);
+
+ /* BIOS is in charge. We should finish any pending transaction */
+ for (i = 0; i < 1; i++) {
+ mutex_lock(&priv->channels[i].mutex);
+ priv->channels[i].suspended = true;
+ mutex_unlock(&priv->channels[i].mutex);
+ }
+
+ return 0;
+}
+
+static int imc_resume(struct pci_dev *dev)
+{
+ int i;
+ struct imc_priv *priv = pci_get_drvdata(dev);
+
+ for (i = 0; i < 1; i++) {
+ mutex_lock(&priv->channels[i].mutex);
+ priv->channels[i].suspended = false;
+ mutex_unlock(&priv->channels[i].mutex);
+ }
+
+ return 0;
+}
+
+static const struct pci_device_id imc_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA) },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, imc_ids);
+
+static struct pci_driver imc_pci_driver = {
+ .name = "imc_smbus",
+ .id_table = imc_ids,
+ .probe = imc_probe,
+ .remove = imc_remove,
+ .suspend = imc_suspend,
+ .resume = imc_resume,
+};
+
+static int __init i2c_imc_init(void)
+{
+ if (!allow_unsafe_access)
+ return -ENODEV;
+
+ pr_warn("using this driver is dangerous unless your firmware is specifically designed for it; use at your own risk\n");
+ return pci_register_driver(&imc_pci_driver);
+}
+module_init(i2c_imc_init);
+
+static void __exit i2c_imc_exit(void)
+{
+ pci_unregister_driver(&imc_pci_driver);
+}
+module_exit(i2c_imc_exit);
+
+module_param(allow_unsafe_access, bool, 0400);
+MODULE_PARM_DESC(allow_unsafe_access, "enable i2c_imc despite potential races against BIOS/hardware bus access");
+
+MODULE_AUTHOR("Andrew Lutomirski ");
+MODULE_DESCRIPTION("iMC SMBus driver");
+MODULE_LICENSE("GPL v2");
+
diff --git a/platform/broadcom/sonic-platform-modules-cel/jaws/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/mc24lc64t.c
new file mode 100644
index 000000000000..ae79770a4d8e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/mc24lc64t.c
@@ -0,0 +1,173 @@
+/*
+ * mc24lc64t.c - driver for Microchip 24LC64T
+ *
+ * Copyright (C) 2017 Celestica Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define EEPROM_SIZE 8192 //mc24lt64t eeprom size in bytes.
+
+struct mc24lc64t_data {
+ struct mutex update_lock;
+};
+
+static ssize_t mc24lc64t_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client = kobj_to_i2c_client(kobj);
+ struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
+ unsigned long timeout, read_time, i = 0;
+ int status;
+
+ mutex_lock(&drvdata->update_lock);
+
+ if (i2c_smbus_write_byte_data(client, off>>8, off))
+ {
+ status = -EIO;
+ goto exit;
+ }
+
+ msleep(1);
+
+begin:
+
+ if (i < count)
+ {
+ timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/
+ do {
+ read_time = jiffies;
+
+ status = i2c_smbus_read_byte(client);
+ if (status >= 0)
+ {
+ buf[i++] = status;
+ goto begin;
+ }
+ } while (time_before(read_time, timeout));
+
+ status = -ETIMEDOUT;
+ goto exit;
+ }
+
+ status = count;
+
+exit:
+ mutex_unlock(&drvdata->update_lock);
+
+ return status;
+}
+
+static ssize_t mc24lc64t_write (struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count){
+
+ struct i2c_client *client = kobj_to_i2c_client(kobj);
+ struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
+ unsigned long timeout, write_time, i = 0;
+ int status;
+ u16 value;
+
+ mutex_lock(&drvdata->update_lock);
+
+begin:
+ if (i < count){
+ timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/
+ value = (buf[i] << 8)| off;
+ do {
+ write_time = jiffies;
+ status = i2c_smbus_write_word_data(client, off>>8, value);
+ if (status >= 0)
+ {
+ // increase offset
+ off++;
+ // increase buffer index
+ i++;
+ goto begin;
+ }
+ } while (time_before(write_time, timeout));
+ status = -ETIMEDOUT;
+ goto exit;
+ }
+ status = count;
+
+exit:
+ mutex_unlock(&drvdata->update_lock);
+ return status;
+}
+
+static struct bin_attribute mc24lc64t_bit_attr = {
+ .attr = {
+ .name = "eeprom",
+ .mode = S_IRUGO | S_IWUGO,
+ },
+ .size = EEPROM_SIZE,
+ .read = mc24lc64t_read,
+ .write = mc24lc64t_write,
+};
+
+static int mc24lc64t_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ struct mc24lc64t_data *drvdata;
+ int err;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
+ | I2C_FUNC_SMBUS_READ_BYTE))
+ return -EPFNOSUPPORT;
+
+ if (!(drvdata = devm_kzalloc(&client->dev,
+ sizeof(struct mc24lc64t_data), GFP_KERNEL)))
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, drvdata);
+ mutex_init(&drvdata->update_lock);
+
+ err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr);
+
+ return err;
+}
+
+static int mc24lc64t_remove(struct i2c_client *client)
+{
+ struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
+ sysfs_remove_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr);
+
+ return 0;
+}
+
+static const struct i2c_device_id mc24lc64t_id[] = {
+ { "24lc64t", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mc24lc64t_id);
+
+static struct i2c_driver mc24lc64t_driver = {
+ .driver = {
+ .name = "mc24lc64t",
+ .owner = THIS_MODULE,
+ },
+ .probe = mc24lc64t_probe,
+ .remove = mc24lc64t_remove,
+ .id_table = mc24lc64t_id,
+};
+
+module_i2c_driver(mc24lc64t_driver);
+
+MODULE_AUTHOR("Abhisit Sangjan ");
+MODULE_DESCRIPTION("Microchip 24LC64T Driver");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-cel/jaws/modules/switchboard_fpga.c b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/switchboard_fpga.c
new file mode 100644
index 000000000000..13afba861088
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/jaws/modules/switchboard_fpga.c
@@ -0,0 +1,2997 @@
+/*
+ * switchboard.c - Driver for Phalanxp Switch FPGA/CPLD.
+ *
+ * Author: Pradchaya Phucharoen
+ *
+ * Copyright (C) 2018 Celestica Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * /
+ * \--sys
+ * \--devices
+ * \--platform
+ * \--AS23128h.switchboard
+ * |--FPGA
+ * |--CPLD[1..4]
+ * \--SFF
+ * \--QSFP[1..128]
+ *
+ */
+
+#ifndef TEST_MODE
+#define MOD_VERSION "0.5.1"
+#else
+#define MOD_VERSION "TEST"
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static int majorNumber;
+
+#define CLASS_NAME "phalanxp_fpga"
+#define DRIVER_NAME "AS14128H.switchboard"
+#define FPGA_PCI_NAME "phalanxp_fpga_pci"
+#define DEVICE_NAME "fwupgrade"
+
+static bool allow_unsafe_i2c_access;
+
+static int smbus_access(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char rw, u8 cmd,
+ int size, union i2c_smbus_data *data);
+
+static int fpga_i2c_access(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char rw, u8 cmd,
+ int size, union i2c_smbus_data *data);
+
+static int i2c_core_init(unsigned int master_bus, unsigned int freq_div,void __iomem *pci_bar);
+static void i2c_core_deinit(unsigned int master_bus, void __iomem *pci_bar);
+static int i2c_xcvr_access(u8 register_address, unsigned int portid, u8 *data, char rw);
+
+static int fpgafw_init(void);
+static void fpgafw_exit(void);
+
+/*
+========================================
+FPGA PCIe BAR 0 Registers
+========================================
+Misc Control 0x00000000 – 0x000000FF
+I2C_CH1 0x00000800 - 0x0000081C
+I2C_CH2 0x00000820 - 0x0000083C
+I2C_CH3 0x00000840 - 0x0000085C
+I2C_CH4 0x00000860 - 0x0000087C
+I2C_CH5 0x00000880 - 0x0000089C
+I2C_CH6 0x000008A0 - 0x000008BC
+I2C_CH7 0x000008C0 - 0x000008DC
+I2C_CH8 0x000008E0 - 0x000008FC
+I2C_CH9 0x00000900 - 0x0000091C
+I2C_CH10 0x00000920 - 0x0000093C
+I2C_CH11 0x00000940 - 0x0000095C
+I2C_CH12 0x00000960 - 0x0000097C
+I2C_CH13 0x00000980 - 0x0000099C
+I2C_CH14 0x000009A0 - 0x000009BC
+SPI Master 0x00000A00 - 0x00000BFC
+PORT XCVR 0x00004000 - 0x00004FFF
+*/
+
+/* MISC */
+#define FPGA_VERSION 0x0000
+#define FPGA_VERSION_MJ_MSK 0xff00
+#define FPGA_VERSION_MN_MSK 0x00ff
+#define FPGA_SCRATCH 0x0004
+#define FPGA_BROAD_TYPE 0x0008
+#define BMC_I2C_SCRATCH 0x0020
+#define FPGA_SLAVE_CPLD_REST 0x0100
+#define FPGA_SWITCH_RESET_CTRL 0x0104
+#define FPAG_PRH_RESER_CTRL 0x0108
+#define FPGA_INT_STATUS 0x0200
+#define FPGA_INT_SRC_STATUS 0x0204
+#define FPGA_INT_FLAG 0x0208
+#define FPGA_INT_MASK 0x020c
+#define FPGA_MISC_CTRL 0x0300
+#define FPGA_MISC_STATUS 0x0304
+
+/* I2C_MASTER BASE ADDR */
+#define I2C_MASTER_FREQ_L 0x0800
+#define I2C_MASTER_FREQ_H 0x0804
+#define I2C_MASTER_CTRL 0x0808
+#define I2C_MASTER_DATA 0x080c
+#define I2C_MASTER_CMD 0x0810 /* Write-Only Register */
+#define I2C_MASTER_STATUS 0x0810 /* Read-Only Register */
+#define I2C_MASTER_CH_1 1
+#define I2C_MASTER_CH_2 2
+#define I2C_MASTER_CH_3 3
+#define I2C_MASTER_CH_4 4
+#define I2C_MASTER_CH_5 5
+#define I2C_MASTER_CH_6 6
+#define I2C_MASTER_CH_7 7
+#define I2C_MASTER_CH_8 8
+#define I2C_MASTER_CH_9 9
+#define I2C_MASTER_CH_10 10
+#define I2C_MASTER_CH_11 11
+#define I2C_MASTER_CH_12 12
+#define I2C_MASTER_CH_13 13
+#define I2C_MASTER_CH_14 14
+
+#define I2C_MASTER_CH_TOTAL I2C_MASTER_CH_14
+
+/* SPI_MASTER */
+#define SPI_MASTER_WR_EN 0x1200 /* one bit */
+#define SPI_MASTER_WR_DATA 0x1204 /* 32 bits */
+#define SPI_MASTER_CHK_ID 0x1208 /* one bit */
+#define SPI_MASTER_VERIFY 0x120c /* one bit */
+#define SPI_MASTER_STATUS 0x1210 /* 15 bits */
+#define SPI_MASTER_MODULE_RST 0x1214 /* one bit */
+
+/* FPGA FRONT PANEL PORT MGMT */
+#define SFF_PORT_CTRL_BASE 0x4000
+#define SFF_PORT_STATUS_BASE 0x4004
+#define SFF_PORT_INT_STATUS_BASE 0x4008
+#define SFF_PORT_INT_MASK_BASE 0x400c
+
+#define PORT_XCVR_REGISTER_SIZE 0x1000
+
+/* PORT CTRL REGISTER
+[31:7] RSVD
+[6] RSVD
+[5] MODSEL 5
+[4] RST 4
+[3:1] RSVD
+[0] TXDIS 0
+*/
+#define CTRL_MODSEL 5
+#define CTRL_RST 4
+#define CTRL_TXDIS 0
+
+/* PORT STATUS REGISTER
+[31:6] RSVD
+[5] IRQ 5
+[4] PRESENT 4
+[3] RSVD
+[2] TXFAULT 2
+[1] RXLOS 1
+[0] MODABS 0
+*/
+#define STAT_IRQ 5
+#define STAT_PRESENT 4
+#define STAT_TXFAULT 2
+#define STAT_RXLOS 1
+#define STAT_MODABS 0
+
+/* PORT INTRPT REGISTER
+[31:6] RSVD
+[5] INT_N 5
+[4] PRESENT 4
+[3] RSVD
+[2] RSVD
+[1] RXLOS 1
+[0] MODABS 0
+*/
+#define INTR_INT_N 5
+#define INTR_PRESENT 4
+#define INTR_TXFAULT 2
+#define INTR_RXLOS 1
+#define INTR_MODABS 0
+
+/* PORT INT MASK REGISTER
+[31:6] RSVD
+[5] INT_N 5
+[4] PRESENT 4
+[3] RSVD
+[2] RSVD
+[1] RXLOS_INT 1
+[0] MODABS 0
+*/
+#define MASK_INT_N 5
+#define MASK_PRESENT 4
+#define MASK_TXFAULT 2
+#define MASK_RXLOS 1
+#define MASK_MODABS 0
+
+
+/**
+ * Switchboard CPLD XCVR registers
+ */
+
+/* PORT SEL REGISTER
+[7:5] RSVD
+[4:0] ID
+*/
+#define I2C_XCVR_SEL 0x10
+#define I2C_SEL_ID 0
+
+/* PORT CTRL REGISTER
+[7:5] RSVD
+[4] RST
+[3:1] RSVD
+[0] TXDIS/MODSEL
+*/
+#define I2C_XCVR_CTRL 0x11
+#define I2C_CTRL_RST 4
+#define I2C_CTRL_MODSEL 0
+#define I2C_CTRL_TXDIS 0
+
+/* PORT STATUS REGISTER
+[7:5] RSVD
+[4] PRESENT/ABS
+[3:2] RSVD
+[1] TXFAULT
+[0] RXLOS/INT_N
+*/
+#define I2C_XCVR_STAT 0x12
+#define I2C_STAT_PRESENT 4
+#define I2C_STAT_MODABS 4
+#define I2C_STAT_TXFAULT 1
+#define I2C_STAT_INT_N 0
+#define I2C_STAT_RXLOS 0
+
+/* PORT INTRPT REGISTER
+[7:5] RSVD
+[4] PRESENT/ABS
+[3:2] RSVD
+[1] TXFAULT
+[0] RXLOS/INT_N
+*/
+#define I2C_XCVR_INRT 0x13
+#define I2C_INTR_PRESENT 4
+#define I2C_INTR_MODABS 4
+#define I2C_INTR_TXFAULT 1
+#define I2C_INTR_INT_N 0
+#define I2C_INTR_RXLOS 0
+
+/* PORT INTR MASK REGISTER
+[31:6] RSVD
+[5] INT_N 5
+[4] PRESENT 4
+[3] RSVD
+[2] RSVD
+[1] RXLOS_INT 1
+[0] MODABS 0
+*/
+#define I2C_XCVR_MASK 0x14
+#define I2C_MASK_PRESENT 4
+#define I2C_MASK_MODABS 4
+#define I2C_MASK_TXFAULT 1
+#define I2C_MASK_INT_N 0
+#define I2C_MASK_RXLOS 0
+
+
+/* I2C master clock speed */
+// NOTE: Only I2C clock in normal mode is support here.
+enum {
+ I2C_DIV_100K = 0x71,
+};
+
+/* I2C Master control register */
+enum {
+ I2C_CTRL_IEN = 6,
+ I2C_CTRL_EN
+};
+
+/* I2C Master command register */
+enum {
+ I2C_CMD_IACK = 0,
+ I2C_CMD_ACK = 3,
+ I2C_CMD_WR,
+ I2C_CMD_RD,
+ I2C_CMD_STO,
+ I2C_CMD_STA,
+};
+
+/* I2C Master status register */
+enum {
+ I2C_STAT_IF = 0,
+ I2C_STAT_TIP,
+ I2C_STAT_AL = 5,
+ I2C_STAT_BUSY,
+ I2C_STAT_RxACK,
+};
+
+/**
+ *
+ * The function is i2c algorithm implement to allow master access to
+ * correct endpoint devices trough the PCA9548 switch devices.
+ *
+ * FPGA I2C Master [mutex resource]
+ * |
+ * |
+ * ---------------------------
+ * | PCA9548(s) |
+ * ---1--2--3--4--5--6--7--8--
+ * | | | | | | | |
+ * EEPROM ... EEPROM
+ *
+ */
+
+#define VIRTUAL_I2C_SFP_PORT 0
+#define VIRTUAL_I2C_QSFP_PORT 128
+
+#define SFF_PORT_TOTAL VIRTUAL_I2C_QSFP_PORT + VIRTUAL_I2C_SFP_PORT
+
+#define VIRTUAL_I2C_BUS_OFFSET 10
+#define BB_CPLD_SLAVE_ADDR 0x0d
+#define FAN_CPLD_SLAVE_ADDR 0x0d
+#define CPLD1_SLAVE_ADDR 0x30
+#define CPLD2_SLAVE_ADDR 0x31
+
+static struct class* fpgafwclass = NULL; // < The device-driver class struct pointer
+static struct device* fpgafwdev = NULL; // < The device-driver device struct pointer
+
+#define PCI_VENDOR_ID_TEST 0x1af4
+
+#ifndef PCI_VENDOR_ID_XILINX
+#define PCI_VENDOR_ID_XILINX 0x10EE
+#endif
+
+#define FPGA_PCIE_DEVICE_ID 0x7021
+#define TEST_PCIE_DEVICE_ID 0x1110
+
+
+#ifdef DEBUG_KERN
+#define info(fmt,args...) printk(KERN_INFO "line %3d : "fmt,__LINE__,##args)
+#define check(REG) printk(KERN_INFO "line %3d : %-8s = %2.2X",__LINE__,#REG,ioread8(REG));
+#else
+#define info(fmt,args...)
+#define check(REG)
+#endif
+
+static struct mutex fpga_i2c_master_locks[I2C_MASTER_CH_TOTAL];
+/* Store lasted switch address and channel */
+static uint16_t fpga_i2c_lasted_access_port[I2C_MASTER_CH_TOTAL];
+static int nack_retry[I2C_MASTER_CH_TOTAL];
+static int need_retry[I2C_MASTER_CH_TOTAL];
+
+enum PORT_TYPE {
+ NONE,
+ QSFP,
+ SFP
+};
+
+struct i2c_switch {
+ unsigned char master_bus; // I2C bus number
+ unsigned char switch_addr; // PCA9548 device address, 0xFF if directly connect to a bus.
+ unsigned char channel; // PCA9548 channel number. If the switch_addr is 0xFF, this value is ignored.
+ enum PORT_TYPE port_type; // QSFP/SFP tranceiver port type.
+ char calling_name[20]; // Calling name.
+};
+
+struct i2c_dev_data {
+ int portid;
+ struct i2c_switch pca9548;
+};
+
+/* PREDEFINED I2C SWITCH DEVICE TOPOLOGY */
+static struct i2c_switch fpga_i2c_bus_dev[] = {
+ /* SFP and QSFP front panel I2C */
+ {I2C_MASTER_CH_11, 0x70, 0, QSFP, "QSFP1"}, {I2C_MASTER_CH_11, 0x70, 1, QSFP, "QSFP2"},
+ {I2C_MASTER_CH_11, 0x70, 2, QSFP, "QSFP3"}, {I2C_MASTER_CH_11, 0x70, 3, QSFP, "QSFP4"},
+ {I2C_MASTER_CH_14, 0x73, 7, QSFP, "QSFP5"}, {I2C_MASTER_CH_14, 0x73, 6, QSFP, "QSFP6"},
+ {I2C_MASTER_CH_14, 0x73, 5, QSFP, "QSFP7"}, {I2C_MASTER_CH_14, 0x73, 4, QSFP, "QSFP8"},
+ {I2C_MASTER_CH_11, 0x70, 4, QSFP, "QSFP9"}, {I2C_MASTER_CH_11, 0x70, 5, QSFP, "QSFP10"},
+ {I2C_MASTER_CH_11, 0x70, 6, QSFP, "QSFP11"}, {I2C_MASTER_CH_11, 0x70, 7, QSFP, "QSFP12"},
+ {I2C_MASTER_CH_14, 0x73, 3, QSFP, "QSFP13"}, {I2C_MASTER_CH_14, 0x73, 2, QSFP, "QSFP14"},
+ {I2C_MASTER_CH_14, 0x73, 1, QSFP, "QSFP15"}, {I2C_MASTER_CH_14, 0x73, 0, QSFP, "QSFP16"},
+
+ {I2C_MASTER_CH_11, 0x71, 0, QSFP, "QSFP17"}, {I2C_MASTER_CH_11, 0x71, 1, QSFP, "QSFP18"},
+ {I2C_MASTER_CH_11, 0x71, 2, QSFP, "QSFP19"}, {I2C_MASTER_CH_11, 0x71, 3, QSFP, "QSFP20"},
+ {I2C_MASTER_CH_14, 0x72, 7, QSFP, "QSFP21"}, {I2C_MASTER_CH_14, 0x72, 6, QSFP, "QSFP22"},
+ {I2C_MASTER_CH_14, 0x72, 5, QSFP, "QSFP23"}, {I2C_MASTER_CH_14, 0x72, 4, QSFP, "QSFP24"},
+ {I2C_MASTER_CH_11, 0x71, 4, QSFP, "QSFP25"}, {I2C_MASTER_CH_11, 0x71, 5, QSFP, "QSFP26"},
+ {I2C_MASTER_CH_11, 0x71, 6, QSFP, "QSFP27"}, {I2C_MASTER_CH_11, 0x71, 7, QSFP, "QSFP28"},
+ {I2C_MASTER_CH_14, 0x72, 3, QSFP, "QSFP29"}, {I2C_MASTER_CH_14, 0x72, 2, QSFP, "QSFP30"},
+ {I2C_MASTER_CH_14, 0x72, 1, QSFP, "QSFP31"}, {I2C_MASTER_CH_14, 0x72, 0, QSFP, "QSFP32"},
+
+ {I2C_MASTER_CH_11, 0x72, 0, QSFP, "QSFP33"}, {I2C_MASTER_CH_11, 0x72, 1, QSFP, "QSFP34"},
+ {I2C_MASTER_CH_11, 0x72, 2, QSFP, "QSFP35"}, {I2C_MASTER_CH_11, 0x72, 3, QSFP, "QSFP36"},
+ {I2C_MASTER_CH_14, 0x71, 7, QSFP, "QSFP37"}, {I2C_MASTER_CH_14, 0x71, 6, QSFP, "QSFP38"},
+ {I2C_MASTER_CH_14, 0x71, 5, QSFP, "QSFP39"}, {I2C_MASTER_CH_14, 0x71, 4, QSFP, "QSFP40"},
+ {I2C_MASTER_CH_11, 0x72, 4, QSFP, "QSFP41"}, {I2C_MASTER_CH_11, 0x72, 5, QSFP, "QSFP42"},
+ {I2C_MASTER_CH_11, 0x72, 6, QSFP, "QSFP43"}, {I2C_MASTER_CH_11, 0x72, 7, QSFP, "QSFP44"},
+ {I2C_MASTER_CH_14, 0x71, 3, QSFP, "QSFP45"}, {I2C_MASTER_CH_14, 0x71, 2, QSFP, "QSFP46"},
+ {I2C_MASTER_CH_14, 0x71, 1, QSFP, "QSFP47"}, {I2C_MASTER_CH_14, 0x71, 0, QSFP, "QSFP48"},
+
+ {I2C_MASTER_CH_11, 0x73, 0, QSFP, "QSFP49"}, {I2C_MASTER_CH_11, 0x73, 1, QSFP, "QSFP50"},
+ {I2C_MASTER_CH_11, 0x73, 2, QSFP, "QSFP51"}, {I2C_MASTER_CH_11, 0x73, 3, QSFP, "QSFP52"},
+ {I2C_MASTER_CH_14, 0x70, 7, QSFP, "QSFP53"}, {I2C_MASTER_CH_14, 0x70, 6, QSFP, "QSFP54"},
+ {I2C_MASTER_CH_14, 0x70, 5, QSFP, "QSFP55"}, {I2C_MASTER_CH_14, 0x70, 4, QSFP, "QSFP56"},
+ {I2C_MASTER_CH_11, 0x73, 4, QSFP, "QSFP57"}, {I2C_MASTER_CH_11, 0x73, 5, QSFP, "QSFP58"},
+ {I2C_MASTER_CH_11, 0x73, 6, QSFP, "QSFP59"}, {I2C_MASTER_CH_11, 0x73, 7, QSFP, "QSFP60"},
+ {I2C_MASTER_CH_14, 0x70, 3, QSFP, "QSFP61"}, {I2C_MASTER_CH_14, 0x70, 2, QSFP, "QSFP62"},
+ {I2C_MASTER_CH_14, 0x70, 1, QSFP, "QSFP63"}, {I2C_MASTER_CH_14, 0x70, 0, QSFP, "QSFP64"},
+
+ {I2C_MASTER_CH_12, 0x70, 0, QSFP, "QSFP65"}, {I2C_MASTER_CH_12, 0x70, 1, QSFP, "QSFP66"},
+ {I2C_MASTER_CH_12, 0x70, 2, QSFP, "QSFP67"}, {I2C_MASTER_CH_12, 0x70, 3, QSFP, "QSFP68"},
+ {I2C_MASTER_CH_13, 0x73, 7, QSFP, "QSFP69"}, {I2C_MASTER_CH_13, 0x73, 6, QSFP, "QSFP70"},
+ {I2C_MASTER_CH_13, 0x73, 5, QSFP, "QSFP71"}, {I2C_MASTER_CH_13, 0x73, 4, QSFP, "QSFP72"},
+ {I2C_MASTER_CH_12, 0x70, 4, QSFP, "QSFP73"}, {I2C_MASTER_CH_12, 0x70, 5, QSFP, "QSFP74"},
+ {I2C_MASTER_CH_12, 0x70, 6, QSFP, "QSFP75"}, {I2C_MASTER_CH_12, 0x70, 7, QSFP, "QSFP76"},
+ {I2C_MASTER_CH_13, 0x73, 3, QSFP, "QSFP77"}, {I2C_MASTER_CH_13, 0x73, 2, QSFP, "QSFP78"},
+ {I2C_MASTER_CH_13, 0x73, 1, QSFP, "QSFP79"}, {I2C_MASTER_CH_13, 0x73, 0, QSFP, "QSFP80"},
+
+ {I2C_MASTER_CH_12, 0x71, 0, QSFP, "QSFP81"}, {I2C_MASTER_CH_12, 0x71, 1, QSFP, "QSFP82"},
+ {I2C_MASTER_CH_12, 0x71, 2, QSFP, "QSFP83"}, {I2C_MASTER_CH_12, 0x71, 3, QSFP, "QSFP84"},
+ {I2C_MASTER_CH_13, 0x72, 7, QSFP, "QSFP85"}, {I2C_MASTER_CH_13, 0x72, 6, QSFP, "QSFP86"},
+ {I2C_MASTER_CH_13, 0x72, 5, QSFP, "QSFP87"}, {I2C_MASTER_CH_13, 0x72, 4, QSFP, "QSFP88"},
+ {I2C_MASTER_CH_12, 0x71, 4, QSFP, "QSFP89"}, {I2C_MASTER_CH_12, 0x71, 5, QSFP, "QSFP90"},
+ {I2C_MASTER_CH_12, 0x71, 6, QSFP, "QSFP91"}, {I2C_MASTER_CH_12, 0x71, 7, QSFP, "QSFP92"},
+ {I2C_MASTER_CH_13, 0x72, 3, QSFP, "QSFP93"}, {I2C_MASTER_CH_13, 0x72, 2, QSFP, "QSFP94"},
+ {I2C_MASTER_CH_13, 0x72, 1, QSFP, "QSFP95"}, {I2C_MASTER_CH_13, 0x72, 0, QSFP, "QSFP96"},
+
+ {I2C_MASTER_CH_12, 0x72, 0, QSFP, "QSFP97"}, {I2C_MASTER_CH_12, 0x72, 1, QSFP, "QSFP98"},
+ {I2C_MASTER_CH_12, 0x72, 2, QSFP, "QSFP99"}, {I2C_MASTER_CH_12, 0x72, 3, QSFP, "QSFP100"},
+ {I2C_MASTER_CH_13, 0x71, 7, QSFP, "QSFP101"}, {I2C_MASTER_CH_13, 0x71, 6, QSFP, "QSFP102"},
+ {I2C_MASTER_CH_13, 0x71, 5, QSFP, "QSFP103"}, {I2C_MASTER_CH_13, 0x71, 4, QSFP, "QSFP104"},
+ {I2C_MASTER_CH_12, 0x72, 4, QSFP, "QSFP105"}, {I2C_MASTER_CH_12, 0x72, 5, QSFP, "QSFP106"},
+ {I2C_MASTER_CH_12, 0x72, 6, QSFP, "QSFP107"}, {I2C_MASTER_CH_12, 0x72, 7, QSFP, "QSFP108"},
+ {I2C_MASTER_CH_13, 0x71, 3, QSFP, "QSFP109"}, {I2C_MASTER_CH_13, 0x71, 2, QSFP, "QSFP110"},
+ {I2C_MASTER_CH_13, 0x71, 1, QSFP, "QSFP111"}, {I2C_MASTER_CH_13, 0x71, 0, QSFP, "QSFP112"},
+
+ {I2C_MASTER_CH_12, 0x73, 0, QSFP, "QSFP113"}, {I2C_MASTER_CH_12, 0x73, 1, QSFP, "QSFP114"},
+ {I2C_MASTER_CH_12, 0x73, 2, QSFP, "QSFP115"}, {I2C_MASTER_CH_12, 0x73, 3, QSFP, "QSFP116"},
+ {I2C_MASTER_CH_13, 0x70, 7, QSFP, "QSFP117"}, {I2C_MASTER_CH_13, 0x70, 6, QSFP, "QSFP118"},
+ {I2C_MASTER_CH_13, 0x70, 5, QSFP, "QSFP119"}, {I2C_MASTER_CH_13, 0x70, 4, QSFP, "QSFP120"},
+ {I2C_MASTER_CH_12, 0x73, 4, QSFP, "QSFP121"}, {I2C_MASTER_CH_12, 0x73, 5, QSFP, "QSFP122"},
+ {I2C_MASTER_CH_12, 0x73, 6, QSFP, "QSFP123"}, {I2C_MASTER_CH_12, 0x73, 7, QSFP, "QSFP124"},
+ {I2C_MASTER_CH_13, 0x70, 3, QSFP, "QSFP125"}, {I2C_MASTER_CH_13, 0x70, 2, QSFP, "QSFP126"},
+ {I2C_MASTER_CH_13, 0x70, 1, QSFP, "QSFP127"}, {I2C_MASTER_CH_13, 0x70, 0, QSFP, "QSFP128"},
+
+ /* Vritual I2C adapters */
+ {I2C_MASTER_CH_1, 0xFF, 0, NONE, "I2C_1"}, // FAN
+ {I2C_MASTER_CH_2, 0xFF, 0, NONE, "I2C_2"},
+ {I2C_MASTER_CH_3, 0xFF, 0, NONE, "I2C_3"},
+ {I2C_MASTER_CH_4, 0xFF, 0, NONE, "I2C_4"},
+ {I2C_MASTER_CH_5, 0xFF, 0, NONE, "I2C_5"}, // BB
+ {I2C_MASTER_CH_6, 0xFF, 0, NONE, "I2C_6"},
+ {I2C_MASTER_CH_7, 0xFF, 0, NONE, "I2C_7"}, // SW[1-2]
+ {I2C_MASTER_CH_8, 0xFF, 0, NONE, "I2C_8"}, // SW[3-4]
+
+ // NOTE: Buses below are for front panel port debug
+ {I2C_MASTER_CH_11, 0xFF, 0, NONE, "I2C_11"},
+ {I2C_MASTER_CH_12, 0xFF, 0, NONE, "I2C_12"},
+ {I2C_MASTER_CH_13, 0xFF, 0, NONE, "I2C_13"},
+ {I2C_MASTER_CH_14, 0xFF, 0, NONE, "I2C_14"},
+};
+
+#define VIRTUAL_I2C_PORT_LENGTH ARRAY_SIZE(fpga_i2c_bus_dev)
+#define FAN_I2C_CPLD_INDEX SFF_PORT_TOTAL
+#define BB_I2C_CPLD_INDEX SFF_PORT_TOTAL + 4
+#define SW1_I2C_CPLD_INDEX SFF_PORT_TOTAL + 6
+#define SW2_I2C_CPLD_INDEX SFF_PORT_TOTAL + 7
+
+struct fpga_device {
+ /* data mmio region */
+ void __iomem *data_base_addr;
+ resource_size_t data_mmio_start;
+ resource_size_t data_mmio_len;
+};
+
+static struct fpga_device fpga_dev = {
+ .data_base_addr = 0,
+ .data_mmio_start = 0,
+ .data_mmio_len = 0,
+};
+
+struct phalanxp_fpga_data {
+ struct device *sff_devices[SFF_PORT_TOTAL];
+ struct i2c_client *sff_i2c_clients[SFF_PORT_TOTAL];
+ struct i2c_adapter *i2c_adapter[VIRTUAL_I2C_PORT_LENGTH];
+ struct mutex fpga_lock; // For FPGA internal lock
+ void __iomem * fpga_read_addr;
+ uint8_t cpld1_read_addr;
+ uint8_t cpld2_read_addr;
+ uint8_t cpld3_read_addr;
+ uint8_t cpld4_read_addr;
+ uint8_t fancpld_read_addr;
+};
+
+struct sff_device_data {
+ int portid;
+ enum PORT_TYPE port_type;
+};
+
+struct phalanxp_fpga_data *fpga_data;
+
+/*
+ * Kernel object for other module drivers.
+ * Other module can use these kobject as a parent.
+ */
+
+static struct kobject *fpga = NULL;
+static struct kobject *cpld1 = NULL;
+static struct kobject *cpld2 = NULL;
+static struct kobject *cpld3 = NULL;
+static struct kobject *cpld4 = NULL;
+static struct kobject *fancpld = NULL;
+
+/**
+ * Device node in sysfs tree.
+ */
+static struct device *sff_dev = NULL;
+
+/**
+ * Show the value of the register set by 'set_fpga_reg_address'
+ * If the address is not set by 'set_fpga_reg_address' first,
+ * The version register is selected by default.
+ * @param buf register value in hextring
+ * @return number of bytes read, or an error code
+ */
+static ssize_t get_fpga_reg_value(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ // read data from the address
+ uint32_t data;
+ data = ioread32(fpga_data->fpga_read_addr);
+ return sprintf(buf, "0x%8.8x\n", data);
+}
+/**
+ * Store the register address
+ * @param buf address wanted to be read value of
+ * @return number of bytes stored, or an error code
+ */
+static ssize_t set_fpga_reg_address(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ uint32_t addr;
+ char *last;
+
+ addr = (uint32_t)strtoul(buf, &last, 16);
+ if (addr == 0 && buf == last) {
+ return -EINVAL;
+ }
+ fpga_data->fpga_read_addr = fpga_dev.data_base_addr + addr;
+ return count;
+}
+/**
+ * Show value of fpga scratch register
+ * @param buf register value in hexstring
+ * @return number of bytes read, or an error code
+ */
+static ssize_t get_fpga_scratch(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ return sprintf(buf, "0x%8.8x\n", ioread32(fpga_dev.data_base_addr + FPGA_SCRATCH) & 0xffffffff);
+}
+/**
+ * Store value of fpga scratch register
+ * @param buf scratch register value passing from user space
+ * @return number of bytes stored, or an error code
+ */
+static ssize_t set_fpga_scratch(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ uint32_t data;
+ char *last;
+ data = (uint32_t)strtoul(buf, &last, 16);
+ if (data == 0 && buf == last) {
+ return -EINVAL;
+ }
+ iowrite32(data, fpga_dev.data_base_addr + FPGA_SCRATCH);
+ return count;
+}
+/**
+ * Store a value in a specific register address
+ * @param buf the value and address in format '0xhhhh 0xhhhhhhhh'
+ * @return number of bytes sent by user space, or an error code
+ */
+static ssize_t set_fpga_reg_value(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ // register are 4 bytes
+ uint32_t addr;
+ uint32_t value;
+ uint32_t mode = 8;
+ char *tok;
+ char clone[count];
+ char *pclone = clone;
+ char *last;
+
+ strcpy(clone, buf);
+
+ mutex_lock(&fpga_data->fpga_lock);
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ addr = (uint32_t)strtoul(tok, &last, 16);
+ if (addr == 0 && tok == last) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ value = (uint32_t)strtoul(tok, &last, 16);
+ if (value == 0 && tok == last) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ mode = 32;
+ } else {
+ mode = (uint32_t)strtoul(tok, &last, 10);
+ if (mode == 0 && tok == last) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ }
+ if (mode == 32) {
+ iowrite32(value, fpga_dev.data_base_addr + addr);
+ } else if (mode == 8) {
+ iowrite8(value, fpga_dev.data_base_addr + addr);
+ } else {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ mutex_unlock(&fpga_data->fpga_lock);
+ return count;
+}
+
+/* FPGA attributes */
+static DEVICE_ATTR( getreg, 0600, get_fpga_reg_value, set_fpga_reg_address);
+static DEVICE_ATTR( scratch, 0600, get_fpga_scratch, set_fpga_scratch);
+static DEVICE_ATTR( setreg, 0200, NULL , set_fpga_reg_value);
+
+static struct attribute *fpga_attrs[] = {
+ &dev_attr_getreg.attr,
+ &dev_attr_scratch.attr,
+ &dev_attr_setreg.attr,
+ NULL,
+};
+
+static struct attribute_group fpga_attr_grp = {
+ .attrs = fpga_attrs,
+};
+
+/* SW CPLDs attributes */
+static ssize_t cpld1_getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ uint8_t data;
+ fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->cpld1_read_addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+static ssize_t cpld1_getreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ uint8_t addr;
+ char *last;
+ addr = (uint8_t)strtoul(buf, &last, 16);
+ if (addr == 0 && buf == last) {
+ return -EINVAL;
+ }
+ fpga_data->cpld1_read_addr = addr;
+ return size;
+}
+struct device_attribute dev_attr_cpld1_getreg = __ATTR(getreg, 0600, cpld1_getreg_show, cpld1_getreg_store);
+
+static ssize_t cpld1_scratch_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ __u8 data;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+static ssize_t cpld1_scratch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ __u8 data;
+ char *last;
+ int err;
+ data = (uint8_t)strtoul(buf, &last, 16);
+ if (data == 0 && buf == last) {
+ return -EINVAL;
+ }
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return size;
+}
+struct device_attribute dev_attr_cpld1_scratch = __ATTR(scratch, 0600, cpld1_scratch_show, cpld1_scratch_store);
+
+static ssize_t cpld1_setreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+
+ uint8_t addr, value;
+ char *tok;
+ char clone[size];
+ char *pclone = clone;
+ int err;
+ char *last;
+
+ strcpy(clone, buf);
+
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ addr = (uint8_t)strtoul(tok, &last, 16);
+ if (addr == 0 && tok == last) {
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ value = (uint8_t)strtoul(tok, &last, 16);
+ if (value == 0 && tok == last) {
+ return -EINVAL;
+ }
+
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&value);
+ if (err < 0)
+ return err;
+
+ return size;
+}
+struct device_attribute dev_attr_cpld1_setreg = __ATTR(setreg, 0200, NULL, cpld1_setreg_store);
+
+static struct attribute *cpld1_attrs[] = {
+ &dev_attr_cpld1_getreg.attr,
+ &dev_attr_cpld1_scratch.attr,
+ &dev_attr_cpld1_setreg.attr,
+ NULL,
+};
+
+static struct attribute_group cpld1_attr_grp = {
+ .attrs = cpld1_attrs,
+};
+
+static ssize_t cpld2_getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ uint8_t data;
+ fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->cpld2_read_addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+
+static ssize_t cpld2_getreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ uint32_t addr;
+ char *last;
+ addr = (uint8_t)strtoul(buf, &last, 16);
+ if (addr == 0 && buf == last) {
+ return -EINVAL;
+ }
+ fpga_data->cpld2_read_addr = addr;
+ return size;
+}
+struct device_attribute dev_attr_cpld2_getreg = __ATTR(getreg, 0600, cpld2_getreg_show, cpld2_getreg_store);
+
+static ssize_t cpld2_scratch_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ __u8 data;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+
+static ssize_t cpld2_scratch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ __u8 data;
+ char *last;
+ int err;
+
+ data = (uint8_t)strtoul(buf, &last, 16);
+ if (data == 0 && buf == last) {
+ return -EINVAL;
+ }
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return size;
+}
+struct device_attribute dev_attr_cpld2_scratch = __ATTR(scratch, 0600, cpld2_scratch_show, cpld2_scratch_store);
+
+static ssize_t cpld2_setreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ uint8_t addr, value;
+ char *tok;
+ char clone[size];
+ char *pclone = clone;
+ int err;
+ char *last;
+
+ strcpy(clone, buf);
+
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ addr = (uint8_t)strtoul(tok, &last, 16);
+ if (addr == 0 && tok == last) {
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ value = (uint8_t)strtoul(tok, &last, 16);
+ if (value == 0 && tok == last) {
+ return -EINVAL;
+ }
+
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&value);
+ if (err < 0)
+ return err;
+
+ return size;
+}
+struct device_attribute dev_attr_cpld2_setreg = __ATTR(setreg, 0200, NULL, cpld2_setreg_store);
+
+static struct attribute *cpld2_attrs[] = {
+ &dev_attr_cpld2_getreg.attr,
+ &dev_attr_cpld2_scratch.attr,
+ &dev_attr_cpld2_setreg.attr,
+ NULL,
+};
+
+static struct attribute_group cpld2_attr_grp = {
+ .attrs = cpld2_attrs,
+};
+
+static ssize_t cpld3_getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ uint8_t data;
+ fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->cpld3_read_addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+
+static ssize_t cpld3_getreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ uint32_t addr;
+ char *last;
+ addr = (uint8_t)strtoul(buf, &last, 16);
+ if (addr == 0 && buf == last) {
+ return -EINVAL;
+ }
+ fpga_data->cpld3_read_addr = addr;
+ return size;
+}
+struct device_attribute dev_attr_cpld3_getreg = __ATTR(getreg, 0600, cpld3_getreg_show, cpld3_getreg_store);
+
+static ssize_t cpld3_scratch_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ __u8 data;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+
+static ssize_t cpld3_scratch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ __u8 data;
+ char *last;
+ int err;
+
+ data = (uint8_t)strtoul(buf, &last, 16);
+ if (data == 0 && buf == last) {
+ return -EINVAL;
+ }
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return size;
+}
+struct device_attribute dev_attr_cpld3_scratch = __ATTR(scratch, 0600, cpld3_scratch_show, cpld3_scratch_store);
+
+static ssize_t cpld3_setreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ uint8_t addr, value;
+ char *tok;
+ char clone[size];
+ char *pclone = clone;
+ int err;
+ char *last;
+
+ strcpy(clone, buf);
+
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ addr = (uint8_t)strtoul(tok, &last, 16);
+ if (addr == 0 && tok == last) {
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ value = (uint8_t)strtoul(tok, &last, 16);
+ if (value == 0 && tok == last) {
+ return -EINVAL;
+ }
+
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&value);
+ if (err < 0)
+ return err;
+
+ return size;
+}
+struct device_attribute dev_attr_cpld3_setreg = __ATTR(setreg, 0200, NULL, cpld3_setreg_store);
+
+static struct attribute *cpld3_attrs[] = {
+ &dev_attr_cpld3_getreg.attr,
+ &dev_attr_cpld3_scratch.attr,
+ &dev_attr_cpld3_setreg.attr,
+ NULL,
+};
+
+static struct attribute_group cpld3_attr_grp = {
+ .attrs = cpld3_attrs,
+};
+
+static ssize_t cpld4_getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ uint8_t data;
+ fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->cpld4_read_addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+
+static ssize_t cpld4_getreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ uint32_t addr;
+ char *last;
+ addr = (uint8_t)strtoul(buf, &last, 16);
+ if (addr == 0 && buf == last) {
+ return -EINVAL;
+ }
+ fpga_data->cpld4_read_addr = addr;
+ return size;
+}
+struct device_attribute dev_attr_cpld4_getreg = __ATTR(getreg, 0600, cpld4_getreg_show, cpld4_getreg_store);
+
+static ssize_t cpld4_scratch_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ __u8 data;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+
+static ssize_t cpld4_scratch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ __u8 data;
+ char *last;
+ int err;
+
+ data = (uint8_t)strtoul(buf, &last, 16);
+ if (data == 0 && buf == last) {
+ return -EINVAL;
+ }
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return size;
+}
+struct device_attribute dev_attr_cpld4_scratch = __ATTR(scratch, 0600, cpld4_scratch_show, cpld4_scratch_store);
+
+static ssize_t cpld4_setreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ uint8_t addr, value;
+ char *tok;
+ char clone[size];
+ char *pclone = clone;
+ int err;
+ char *last;
+
+ strcpy(clone, buf);
+
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ addr = (uint8_t)strtoul(tok, &last, 16);
+ if (addr == 0 && tok == last) {
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ value = (uint8_t)strtoul(tok, &last, 16);
+ if (value == 0 && tok == last) {
+ return -EINVAL;
+ }
+
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&value);
+ if (err < 0)
+ return err;
+
+ return size;
+}
+struct device_attribute dev_attr_cpld4_setreg = __ATTR(setreg, 0200, NULL, cpld4_setreg_store);
+
+static struct attribute *cpld4_attrs[] = {
+ &dev_attr_cpld4_getreg.attr,
+ &dev_attr_cpld4_scratch.attr,
+ &dev_attr_cpld4_setreg.attr,
+ NULL,
+};
+
+static struct attribute_group cpld4_attr_grp = {
+ .attrs = cpld4_attrs,
+};
+
+/* FAN CPLD */
+static ssize_t fancpld_getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ uint8_t data;
+ fpga_i2c_access(fpga_data->i2c_adapter[FAN_I2C_CPLD_INDEX], FAN_CPLD_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->fancpld_read_addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+static ssize_t fancpld_getreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ uint8_t addr;
+ char *last;
+ addr = (uint8_t)strtoul(buf, &last, 16);
+ if (addr == 0 && buf == last) {
+ return -EINVAL;
+ }
+ fpga_data->fancpld_read_addr = addr;
+ return size;
+}
+struct device_attribute dev_attr_fancpld_getreg = __ATTR(getreg, 0600, fancpld_getreg_show, fancpld_getreg_store);
+
+static ssize_t fancpld_scratch_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ __u8 data;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[FAN_I2C_CPLD_INDEX], FAN_CPLD_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x04, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+static ssize_t fancpld_scratch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ __u8 data;
+ char *last;
+ int err;
+ data = (uint8_t)strtoul(buf, &last, 16);
+ if (data == 0 && buf == last) {
+ return -EINVAL;
+ }
+ err = fpga_i2c_access(fpga_data->i2c_adapter[FAN_I2C_CPLD_INDEX], FAN_CPLD_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x04, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return size;
+}
+struct device_attribute dev_attr_fancpld_scratch = __ATTR(scratch, 0600, fancpld_scratch_show, fancpld_scratch_store);
+
+static ssize_t fancpld_setreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+
+ uint8_t addr, value;
+ char *tok;
+ char clone[size];
+ char *pclone = clone;
+ int err;
+ char *last;
+
+ strcpy(clone, buf);
+
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ addr = (uint8_t)strtoul(tok, &last, 16);
+ if (addr == 0 && tok == last) {
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ value = (uint8_t)strtoul(tok, &last, 16);
+ if (value == 0 && tok == last) {
+ return -EINVAL;
+ }
+
+ err = fpga_i2c_access(fpga_data->i2c_adapter[FAN_I2C_CPLD_INDEX], FAN_CPLD_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&value);
+ if (err < 0)
+ return err;
+
+ return size;
+}
+struct device_attribute dev_attr_fancpld_setreg = __ATTR(setreg, 0200, NULL, fancpld_setreg_store);
+
+static struct attribute *fancpld_attrs[] = {
+ &dev_attr_fancpld_getreg.attr,
+ &dev_attr_fancpld_scratch.attr,
+ &dev_attr_fancpld_setreg.attr,
+ NULL,
+};
+
+static struct attribute_group fancpld_attr_grp = {
+ .attrs = fancpld_attrs,
+};
+
+static struct attribute *fancpld_no_attrs[] = {
+ NULL,
+};
+
+static struct attribute_group fancpld_no_attr_grp = {
+ .attrs = fancpld_no_attrs,
+};
+
+/* QSFP/SFP+ attributes */
+static ssize_t qsfp_modirq_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_STAT,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_STAT_INT_N) & 1U);
+}
+DEVICE_ATTR_RO(qsfp_modirq);
+
+static ssize_t qsfp_modprs_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_STAT,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_STAT_MODABS) & 1U);
+}
+DEVICE_ATTR_RO(qsfp_modprs);
+
+static ssize_t sfp_txfault_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_STAT,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_STAT_TXFAULT) & 1U);
+}
+DEVICE_ATTR_RO(sfp_txfault);
+
+static ssize_t sfp_rxlos_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_STAT,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_STAT_RXLOS) & 1U);
+}
+DEVICE_ATTR_RO(sfp_rxlos);
+
+static ssize_t sfp_modabs_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_STAT,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_STAT_MODABS) & 1U);
+}
+DEVICE_ATTR_RO(sfp_modabs);
+
+static ssize_t qsfp_modsel_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_CTRL_MODSEL) & 1U);
+}
+static ssize_t qsfp_modsel_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ ssize_t status;
+ long value;
+ u8 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+
+ status = kstrtol(buf, 0, &value);
+ if (status == 0) {
+ // if value is 0, clear bit.
+ i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_READ);
+ if (!value)
+ data = data & ~( 1U << I2C_CTRL_MODSEL );
+ else
+ data = data | ( 1U << I2C_CTRL_MODSEL );
+ i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_WRITE);
+ status = size;
+ }
+ return status;
+}
+DEVICE_ATTR_RW(qsfp_modsel);
+
+static ssize_t qsfp_reset_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_CTRL_RST) & 1U);
+}
+
+static ssize_t qsfp_reset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ ssize_t status;
+ long value;
+ u8 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+
+ status = kstrtol(buf, 0, &value);
+ if (status == 0) {
+ // if value is 0, reset signal is low
+ i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_READ);
+ if (!value)
+ data = data & ~((u8)0x1 << I2C_CTRL_RST);
+ else
+ data = data | ((u8)0x1 << I2C_CTRL_RST);
+ i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_WRITE);
+ status = size;
+ }
+ return status;
+}
+DEVICE_ATTR_RW(qsfp_reset);
+
+static ssize_t sfp_txdisable_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_CTRL_TXDIS) & 1U);
+}
+static ssize_t sfp_txdisable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ ssize_t status;
+ long value;
+ u8 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ status = kstrtol(buf, 0, &value);
+ if (status == 0) {
+ // check if value is 0 clear
+ i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_READ);
+ if (!value)
+ data = data & ~((u8)0x1 << I2C_CTRL_TXDIS);
+ else
+ data = data | ((u8)0x1 << I2C_CTRL_TXDIS);
+ i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_WRITE);
+ status = size;
+ }
+ mutex_unlock(&fpga_data->fpga_lock);
+ return status;
+}
+DEVICE_ATTR_RW(sfp_txdisable);
+
+static struct attribute *sff_attrs[] = {
+ &dev_attr_qsfp_modirq.attr,
+ &dev_attr_qsfp_modprs.attr,
+ &dev_attr_qsfp_modsel.attr,
+ &dev_attr_qsfp_reset.attr,
+ &dev_attr_sfp_txfault.attr,
+ &dev_attr_sfp_rxlos.attr,
+ &dev_attr_sfp_modabs.attr,
+ &dev_attr_sfp_txdisable.attr,
+ NULL,
+};
+
+static struct attribute_group sff_attr_grp = {
+ .attrs = sff_attrs,
+};
+
+static const struct attribute_group *sff_attr_grps[] = {
+ &sff_attr_grp,
+ NULL
+};
+
+
+static ssize_t port_led_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // value can be "nomal", "test"
+ __u8 led_mode_1, led_mode_2, led_mode_3, led_mode_4;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1);
+ if (err < 0)
+ return err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_2);
+ if (err < 0)
+ return err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_3);
+ if (err < 0)
+ return err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_4);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "%s %s %s %s\n",
+ led_mode_1 ? "test" : "normal",
+ led_mode_2 ? "test" : "normal",
+ led_mode_3 ? "test" : "normal",
+ led_mode_4 ? "test" : "normal");
+}
+static ssize_t port_led_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ int status;
+ __u8 led_mode_1;
+ if (sysfs_streq(buf, "test")) {
+ led_mode_1 = 0x01;
+ } else if (sysfs_streq(buf, "normal")) {
+ led_mode_1 = 0x00;
+ } else {
+ return -EINVAL;
+ }
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1);
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1);
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1);
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1);
+ return size;
+}
+DEVICE_ATTR_RW(port_led_mode);
+
+// Only work when port_led_mode set to 1
+static ssize_t port_led_color_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // value can be green/amber/both/alt-blink/OFF
+ __u8 led_color1, led_color2, led_color3, led_color4;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color1);
+ if (err < 0)
+ return err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color2);
+ if (err < 0)
+ return err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color3);
+ if (err < 0)
+ return err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color4);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "%s %s %s %s\n",
+ led_color1 == 0x07 ? "off" : led_color1 == 0x06 ? "green" : led_color1 == 0x05 ? "amber" : led_color1 == 0x04 ?
+ "both" : "alt-blink",
+ led_color1 == 0x07 ? "off" : led_color1 == 0x06 ? "green" : led_color1 == 0x05 ? "amber" : led_color1 == 0x04 ?
+ "both" : "alt-blink",
+ led_color1 == 0x07 ? "off" : led_color1 == 0x06 ? "green" : led_color1 == 0x05 ? "amber" : led_color1 == 0x04 ?
+ "both" : "alt-blink",
+ led_color1 == 0x07 ? "off" : led_color1 == 0x06 ? "green" : led_color1 == 0x05 ? "amber" : led_color1 == 0x04 ?
+ "both" : "alt-blink");
+}
+
+static ssize_t port_led_color_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ int status;
+ __u8 led_color;
+ if (sysfs_streq(buf, "off")) {
+ led_color = 0x07;
+ } else if (sysfs_streq(buf, "green")) {
+ led_color = 0x06;
+ } else if (sysfs_streq(buf, "amber")) {
+ led_color = 0x05;
+ } else if (sysfs_streq(buf, "both")) {
+ led_color = 0x04;
+ } else if (sysfs_streq(buf, "alt-blink")) {
+ led_color = 0x03;
+ } else {
+ status = -EINVAL;
+ return status;
+ }
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x0A, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color);
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x0A, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color);
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x0A, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color);
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x0A, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color);
+ return size;
+}
+DEVICE_ATTR_RW(port_led_color);
+
+static struct attribute *sff_led_test[] = {
+ &dev_attr_port_led_mode.attr,
+ &dev_attr_port_led_color.attr,
+ NULL,
+};
+
+static struct attribute_group sff_led_test_grp = {
+ .attrs = sff_led_test,
+};
+
+static struct device * phalanxp_sff_init(int portid) {
+ struct sff_device_data *new_data;
+ struct device *new_device;
+
+ new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
+ if (!new_data) {
+ printk(KERN_ALERT "Cannot alloc sff device data @port%d", portid);
+ return NULL;
+ }
+ /* The QSFP port ID start from 1 */
+ new_data->portid = portid + 1;
+ new_data->port_type = fpga_i2c_bus_dev[portid].port_type;
+ new_device = device_create_with_groups(fpgafwclass, sff_dev, MKDEV(0, 0), new_data, sff_attr_grps, "%s", fpga_i2c_bus_dev[portid].calling_name);
+ if (IS_ERR(new_device)) {
+ printk(KERN_ALERT "Cannot create sff device @port%d", portid);
+ kfree(new_data);
+ return NULL;
+ }
+ return new_device;
+}
+
+static int i2c_core_init(unsigned int master_bus, unsigned int freq_div,void __iomem *pci_bar){
+
+ unsigned int ctrl;
+ unsigned int REG_FREQ_L;
+ unsigned int REG_FREQ_H;
+ unsigned int REG_CTRL;
+ unsigned int REG_CMD;
+
+ REG_FREQ_L = I2C_MASTER_FREQ_L + (master_bus - 1) * 0x20;
+ REG_FREQ_H = I2C_MASTER_FREQ_H + (master_bus - 1) * 0x20;
+ REG_CTRL = I2C_MASTER_CTRL + (master_bus - 1) * 0x20;
+ REG_CMD = I2C_MASTER_CMD + (master_bus - 1) * 0x20;
+
+ if ( freq_div != I2C_DIV_100K ) {
+ printk(KERN_ERR "FPGA I2C core: Unsupported clock divider: %x\n", freq_div);
+ return -EINVAL;
+ }
+
+ // Makes sure core is disable
+ ctrl = ioread8(pci_bar + REG_CTRL);
+ iowrite8( ctrl & ~(1 << I2C_CTRL_EN | 1 << I2C_CTRL_IEN), pci_bar + REG_CTRL);
+
+ iowrite8( freq_div & 0xFF , pci_bar + REG_FREQ_L);
+ iowrite8( freq_div >> 8, pci_bar + REG_FREQ_H);
+
+ /* Only enable EN bit, we only use polling mode */
+ iowrite8(1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+ iowrite8(1 << I2C_CTRL_EN, pci_bar + REG_CTRL);
+
+ return 0;
+}
+
+static void i2c_core_deinit(unsigned int master_bus,void __iomem *pci_bar){
+
+ unsigned int REG_CTRL;
+ REG_CTRL = I2C_MASTER_CTRL + (master_bus - 1) * 0x20;
+ // Disable core
+ iowrite8( ioread8(pci_bar + REG_CTRL) & ~(1 << I2C_CTRL_EN| 1 << I2C_CTRL_IEN), pci_bar + REG_CTRL);
+}
+
+/**
+ * We have 2 line cards and each with 2 cplds here.
+ * Each line card have 64 ports. Each cpld manage 32 ports.
+ * protid start from 1.
+ * +---+------------------+------------------+
+ * |LC1|1 CPLD1 57|65 CPLD2 121|
+ * | |4 60|68 124|
+ * +---+------------------+------------------+
+ * |LC2|5 CPLD1 61|69 CPLD2 125|
+ * | |8 64|72 128|
+ * +---+------------------+------------------+
+ */
+static int i2c_xcvr_access(u8 register_address, unsigned int portid, u8 *data, char rw){
+
+ u16 dev_addr = 0;
+ int err;
+ int lci, cpldi, i2c_adapter_index;
+ int row, col;
+
+ /* check for portid valid length */
+ if(portid < 1 || portid > SFF_PORT_TOTAL){
+ return -EINVAL;
+ }
+
+ lci = ( portid -1 ) % 8;
+ cpldi = (portid -1 ) / 8;
+
+ /* Normalize the port xposition into 4 x 8 metric.
+ * Then calculate the cpld's port index from matrix.
+ */
+ row = (portid -1 ) % 4;
+ col = (portid -1 ) / 8;
+
+ // Line card select top/buttom
+ if( lci < 4 ){
+ i2c_adapter_index = SW1_I2C_CPLD_INDEX;
+ }else{
+ i2c_adapter_index = SW2_I2C_CPLD_INDEX;
+ }
+
+ // CPLD select left/right
+ if( cpldi < 8 ){
+ dev_addr = CPLD1_SLAVE_ADDR;
+ }else{
+ col -= 8;
+ dev_addr = CPLD2_SLAVE_ADDR;
+ }
+
+ // Calculate cpld portid
+ portid = ( 4 * col ) + row + 1;
+
+ // Select port
+ err = fpga_i2c_access(fpga_data->i2c_adapter[i2c_adapter_index], dev_addr, 0x00, I2C_SMBUS_WRITE,
+ I2C_XCVR_SEL, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&portid);
+ if(err < 0){
+ return err;
+ }
+ // Read/write port xcvr register
+ err = fpga_i2c_access(fpga_data->i2c_adapter[i2c_adapter_index], dev_addr, 0x00, rw,
+ register_address , I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)data);
+ if(err < 0){
+ return err;
+ }
+ return 0;
+}
+
+static int i2c_wait_ack(struct i2c_adapter *a, unsigned long timeout, int writing) {
+ int error = 0;
+ int Status;
+
+ struct i2c_dev_data *new_data = i2c_get_adapdata(a);
+ void __iomem *pci_bar = fpga_dev.data_base_addr;
+
+ unsigned int REG_FREQ_L;
+ unsigned int REG_FREQ_H;
+ unsigned int REG_CMD;
+ unsigned int REG_CTRL;
+ unsigned int REG_STAT;
+ unsigned int REG_DATA;
+
+ unsigned int master_bus = new_data->pca9548.master_bus;
+
+ if (master_bus < I2C_MASTER_CH_1 || master_bus > I2C_MASTER_CH_TOTAL) {
+ error = -EINVAL;
+ return error;
+ }
+
+ REG_FREQ_L = I2C_MASTER_FREQ_L + (master_bus - 1) * 0x20;
+ REG_FREQ_H = I2C_MASTER_FREQ_H + (master_bus - 1) * 0x20;
+ REG_CTRL = I2C_MASTER_CTRL + (master_bus - 1) * 0x20;
+ REG_CMD = I2C_MASTER_CMD + (master_bus - 1) * 0x20;
+ REG_STAT = I2C_MASTER_STATUS + (master_bus - 1) * 0x20;
+ REG_DATA = I2C_MASTER_DATA + (master_bus - 1) * 0x20;
+
+ check(pci_bar + REG_STAT);
+ check(pci_bar + REG_CTRL);
+
+ /*
+ * We wait for the data to be transferred (8bit),
+ * then we start polling on the ACK/NACK bit
+ * udelay((8 * 1000) / 100);
+ */
+ udelay(80);
+ dev_dbg(&a->dev,"Wait for 0x%2.2X\n", 1 << I2C_STAT_TIP);
+
+ timeout = jiffies + msecs_to_jiffies(timeout);
+ while (1) {
+ Status = ioread8(pci_bar + REG_STAT);
+ dev_dbg(&a->dev, "ST:%2.2X\n", Status);
+
+ /* Wait for the TIP bit to be cleared before timeout */
+ if ( (Status & ( 1 << I2C_STAT_TIP )) == 0 ) {
+ dev_dbg(&a->dev, " TIP cleared:0x%2.2X\n", Status);
+ break;
+ }
+
+ if (time_after(jiffies, timeout)) {
+ info("Status %2.2X", Status);
+ info("Error Timeout");
+ error = -ETIMEDOUT;
+ break;
+ }
+
+ cpu_relax();
+ cond_resched();
+ }
+ info("Status %2.2X", Status);
+ info("STA:%x",Status);
+
+ if (error < 0) {
+ dev_dbg(&a->dev, "%s TIMEOUT bit 0x%x not clear in specific time\n",
+ __func__, (1 << I2C_STAT_TIP));
+ return error;
+ }
+
+ /** There is only one master in each bus. If this error happen something is
+ * not normal in i2c transfer refer to:
+ * https://www.i2c-bus.org/i2c-primer/analysing-obscure-problems/master-reports-arbitration-lost
+ */
+ // Arbitration lost
+ if (Status & (1 << I2C_STAT_AL)) {
+ info("Error arbitration lost");
+ nack_retry[master_bus - 1] = 1;
+ return -EBUSY;
+ }
+
+ // Ack not received
+ if (Status & (1 << I2C_STAT_RxACK)) {
+ info( "SL No ACK");
+ if (writing) {
+ info("Error No ACK");
+ nack_retry[master_bus - 1] = 1;
+ return -EIO;
+ }
+ } else {
+ info( "SL ACK");
+ }
+
+ return error;
+}
+
+static int i2c_wait_stop(struct i2c_adapter *a, unsigned long timeout, int writing) {
+ int error = 0;
+ int Status;
+
+ struct i2c_dev_data *new_data = i2c_get_adapdata(a);
+ void __iomem *pci_bar = fpga_dev.data_base_addr;
+
+ unsigned int REG_FREQ_L;
+ unsigned int REG_FREQ_H;
+ unsigned int REG_CMD;
+ unsigned int REG_CTRL;
+ unsigned int REG_STAT;
+ unsigned int REG_DATA;
+
+ unsigned int master_bus = new_data->pca9548.master_bus;
+
+ if (master_bus < I2C_MASTER_CH_1 || master_bus > I2C_MASTER_CH_TOTAL) {
+ error = -EINVAL;
+ return error;
+ }
+
+ REG_FREQ_L = I2C_MASTER_FREQ_L + (master_bus - 1) * 0x20;
+ REG_FREQ_H = I2C_MASTER_FREQ_H + (master_bus - 1) * 0x20;
+ REG_CTRL = I2C_MASTER_CTRL + (master_bus - 1) * 0x20;
+ REG_CMD = I2C_MASTER_CMD + (master_bus - 1) * 0x20;
+ REG_STAT = I2C_MASTER_STATUS + (master_bus - 1) * 0x20;
+ REG_DATA = I2C_MASTER_DATA + (master_bus - 1) * 0x20;
+
+ check(pci_bar + REG_STAT);
+ check(pci_bar + REG_CTRL);
+
+ dev_dbg(&a->dev,"Wait for 0x%2.2X\n", 1 << I2C_STAT_BUSY);
+ timeout = jiffies + msecs_to_jiffies(timeout);
+ while (1) {
+ Status = ioread8(pci_bar + REG_STAT);
+ dev_dbg(&a->dev, "ST:%2.2X\n", Status);
+ if (time_after(jiffies, timeout)) {
+ info("Status %2.2X", Status);
+ info("Error Timeout");
+ error = -ETIMEDOUT;
+ break;
+ }
+
+ /* Wait for the BUSY bit to be cleared before timeout */
+ if ( (Status & ( 1 << I2C_STAT_BUSY )) == 0 ) {
+ dev_dbg(&a->dev, " BUSY cleared:0x%2.2X\n", Status);
+ break;
+ }
+
+ cpu_relax();
+ cond_resched();
+ }
+ info("Status %2.2X", Status);
+ info("STA:%x",Status);
+
+ if (error < 0) {
+ dev_dbg(&a->dev, "%s TIMEOUT bit 0x%x not clear in specific time\n",
+ __func__, (1 << I2C_STAT_BUSY));
+ return error;
+ }
+ return 0;
+}
+
+/* SMBUS Xfer for opencore I2C with polling */
+// TODO: Change smbus_xfer to master_xfer - This will support i2c and all smbus emu functions.
+static int smbus_access(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char rw, u8 cmd,
+ int size, union i2c_smbus_data *data)
+{
+ int error = 0;
+ int cnt = 0;
+ int bid = 0;
+ struct i2c_dev_data *dev_data;
+ void __iomem *pci_bar;
+ unsigned int portid, master_bus;
+ int error_stop = 0;
+
+ unsigned int REG_FREQ_L;
+ unsigned int REG_FREQ_H;
+ unsigned int REG_CMD;
+ unsigned int REG_CTRL;
+ unsigned int REG_STAT;
+ unsigned int REG_DATA;
+
+ REG_FREQ_L = 0;
+ REG_FREQ_H = 0;
+ REG_CTRL = 0;
+ REG_CMD = 0;
+ REG_STAT = 0;
+ REG_DATA = 0;
+
+ /* Write the command register */
+ dev_data = i2c_get_adapdata(adapter);
+ portid = dev_data->portid;
+ pci_bar = fpga_dev.data_base_addr;
+
+#ifdef DEBUG_KERN
+ printk(KERN_INFO "portid %2d|@ 0x%2.2X|f 0x%4.4X|(%d)%-5s| (%d)%-10s|CMD %2.2X "
+ , portid, addr, flags, rw, rw == 1 ? "READ " : "WRITE"
+ , size, size == 0 ? "QUICK" :
+ size == 1 ? "BYTE" :
+ size == 2 ? "BYTE_DATA" :
+ size == 3 ? "WORD_DATA" :
+ size == 4 ? "PROC_CALL" :
+ size == 5 ? "BLOCK_DATA" :
+ size == 8 ? "I2C_BLOCK_DATA" : "ERROR"
+ , cmd);
+#endif
+
+ master_bus = dev_data->pca9548.master_bus;
+ error = i2c_core_init(master_bus, I2C_DIV_100K, fpga_dev.data_base_addr);
+
+ /* Map the size to what the chip understands */
+ switch (size) {
+ case I2C_SMBUS_QUICK:
+ case I2C_SMBUS_BYTE:
+ case I2C_SMBUS_BYTE_DATA:
+ case I2C_SMBUS_WORD_DATA:
+ case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ break;
+ default:
+ printk(KERN_INFO "Unsupported transaction %d\n", size);
+ error = -EOPNOTSUPP;
+ goto Done;
+ }
+
+ master_bus = dev_data->pca9548.master_bus;
+
+ if (master_bus < I2C_MASTER_CH_1 || master_bus > I2C_MASTER_CH_TOTAL) {
+ error = -EINVAL;
+ goto Done;
+ }
+
+ REG_FREQ_L = I2C_MASTER_FREQ_L + (master_bus - 1) * 0x20;
+ REG_FREQ_H = I2C_MASTER_FREQ_H + (master_bus - 1) * 0x20;
+ REG_CTRL = I2C_MASTER_CTRL + (master_bus - 1) * 0x20;
+ REG_CMD = I2C_MASTER_CMD + (master_bus - 1) * 0x20;
+ REG_STAT = I2C_MASTER_STATUS + (master_bus - 1) * 0x20;
+ REG_DATA = I2C_MASTER_DATA + (master_bus - 1) * 0x20;
+
+ ////[S][ADDR/R]
+ if (rw == I2C_SMBUS_READ &&
+ (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE)) {
+ // sent device address with Read mode
+ iowrite8( (addr << 1) | 0x01, pci_bar + REG_DATA);
+ } else {
+ // sent device address with Write mode
+ iowrite8( (addr << 1) & 0xFE, pci_bar + REG_DATA);
+ }
+ iowrite8( 1 << I2C_CMD_STA | 1 << I2C_CMD_WR | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+
+ info( "MS Start");
+
+ //// Wait {A}
+ // + IACK
+ error = i2c_wait_ack(adapter, 30, 1);
+ if (error < 0) {
+ info( "get error %d", error);
+ dev_dbg(&adapter->dev,"START Error: %d\n", error);
+ goto Done;
+ }
+
+ //// [CMD]{A}
+ if (size == I2C_SMBUS_BYTE_DATA ||
+ size == I2C_SMBUS_WORD_DATA ||
+ size == I2C_SMBUS_BLOCK_DATA ||
+ size == I2C_SMBUS_I2C_BLOCK_DATA ||
+ (size == I2C_SMBUS_BYTE && rw == I2C_SMBUS_WRITE)) {
+
+ // sent command code to data register
+ iowrite8(cmd, pci_bar + REG_DATA);
+ // Start the transfer
+ iowrite8(1 << I2C_CMD_WR | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+ info( "MS Send CMD 0x%2.2X", cmd);
+
+ // Wait {A}
+ // IACK
+ error = i2c_wait_ack(adapter, 30, 1);
+ if (error < 0) {
+ info( "get error %d", error);
+ dev_dbg(&adapter->dev,"CMD Error: %d\n", error);
+ goto Done;
+ }
+ }
+
+ switch (size) {
+ case I2C_SMBUS_BYTE_DATA:
+ cnt = 1; break;
+ case I2C_SMBUS_WORD_DATA:
+ cnt = 2; break;
+ case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ /* in block data mode keep number of byte in block[0] */
+ cnt = data->block[0];
+ break;
+ default:
+ cnt = 0; break;
+ }
+
+ // [CNT] used only block data write
+ if (size == I2C_SMBUS_BLOCK_DATA && rw == I2C_SMBUS_WRITE) {
+
+ iowrite8(cnt, pci_bar + REG_DATA);
+ //Start the transfer
+ iowrite8(1 << I2C_CMD_WR | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+ info( "MS Send CNT 0x%2.2X", cnt);
+
+ // Wait {A}
+ // IACK
+ error = i2c_wait_ack(adapter, 30, 1);
+ if (error < 0) {
+ info( "get error %d", error);
+ dev_dbg(&adapter->dev,"CNT Error: %d\n", error);
+ goto Done;
+ }
+ }
+
+ // [DATA]{A}
+ if ( rw == I2C_SMBUS_WRITE && (
+ size == I2C_SMBUS_BYTE ||
+ size == I2C_SMBUS_BYTE_DATA ||
+ size == I2C_SMBUS_WORD_DATA ||
+ size == I2C_SMBUS_BLOCK_DATA ||
+ size == I2C_SMBUS_I2C_BLOCK_DATA
+ )) {
+ int bid = 0;
+ info( "MS prepare to sent [%d bytes]", cnt);
+ if (size == I2C_SMBUS_BLOCK_DATA || size == I2C_SMBUS_I2C_BLOCK_DATA) {
+ bid = 1; // block[0] is cnt;
+ cnt += 1; // offset from block[0]
+ }
+ for (; bid < cnt; bid++) {
+ info("STA:%x", ioread8(pci_bar + REG_STAT) );
+ info( " Data > %2.2X", data->block[bid]);
+ iowrite8(data->block[bid], pci_bar + REG_DATA);
+ iowrite8(1 << I2C_CMD_WR | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+
+ // Wait {A}
+ // IACK
+ error = i2c_wait_ack(adapter, 30, 1);
+ if (error < 0) {
+ dev_dbg(&adapter->dev,"Send DATA Error: %d\n", error);
+ goto Done;
+ }
+ }
+ }
+
+ //REPEATE START
+ if ( rw == I2C_SMBUS_READ && (
+ size == I2C_SMBUS_BYTE_DATA ||
+ size == I2C_SMBUS_WORD_DATA ||
+ size == I2C_SMBUS_BLOCK_DATA ||
+ size == I2C_SMBUS_I2C_BLOCK_DATA
+ )) {
+ info( "MS Repeated Start");
+
+ // sent Address with Read mode
+ iowrite8( addr << 1 | 0x1 , pci_bar + REG_DATA);
+ // SET START | WRITE
+ iowrite8( 1 << I2C_CMD_STA | 1 << I2C_CMD_WR | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+
+ // Wait {A}
+ error = i2c_wait_ack(adapter, 30, 1);
+ if (error < 0) {
+ dev_dbg(&adapter->dev,"Repeat START Error: %d\n", error);
+ goto Done;
+ }
+
+ }
+
+ if ( rw == I2C_SMBUS_READ && (
+ size == I2C_SMBUS_BYTE ||
+ size == I2C_SMBUS_BYTE_DATA ||
+ size == I2C_SMBUS_WORD_DATA ||
+ size == I2C_SMBUS_BLOCK_DATA ||
+ size == I2C_SMBUS_I2C_BLOCK_DATA
+ )) {
+
+ switch (size) {
+ case I2C_SMBUS_BYTE:
+ case I2C_SMBUS_BYTE_DATA:
+ cnt = 1; break;
+ case I2C_SMBUS_WORD_DATA:
+ cnt = 2; break;
+ case I2C_SMBUS_BLOCK_DATA:
+ /* will be changed after recived first data */
+ cnt = 3; break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ cnt = data->block[0]; break;
+ default:
+ cnt = 0; break;
+ }
+
+ info( "MS Receive");
+
+ for (bid = 0; bid < cnt; bid++) {
+
+ // Start receive FSM
+ if (bid == cnt - 1) {
+ info( "READ NACK");
+ iowrite8(1 << I2C_CMD_RD | 1 << I2C_CMD_ACK | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+ }else{
+
+ iowrite8(1 << I2C_CMD_RD, pci_bar + REG_CMD);
+ }
+
+ // Wait {A}
+ error = i2c_wait_ack(adapter, 30, 0);
+ if(nack_retry[master_bus - 1] == 1)
+ {
+ need_retry[master_bus - 1] = 1;
+ }
+ if (error < 0) {
+ dev_dbg(&adapter->dev,"Receive DATA Error: %d\n", error);
+ goto Done;
+ }
+ if(size == I2C_SMBUS_I2C_BLOCK_DATA){
+ /* block[0] is read length */
+ data->block[bid+1] = ioread8(pci_bar + REG_DATA);
+ info( "DATA IN [%d] %2.2X", bid+1, data->block[bid+1]);
+ }else {
+ data->block[bid] = ioread8(pci_bar + REG_DATA);
+ info( "DATA IN [%d] %2.2X", bid, data->block[bid]);
+ }
+ if (size == I2C_SMBUS_BLOCK_DATA && bid == 0) {
+ cnt = data->block[0] + 1;
+ }
+ }
+ }
+
+Done:
+ info( "MS STOP");
+ // SET STOP
+ iowrite8( 1 << I2C_CMD_STO | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+ // Wait for the STO to finish.
+ error_stop = i2c_wait_stop(adapter, 30, 0);
+ if (error_stop < 0) {
+ dev_dbg(&adapter->dev,"STOP Error: %d\n", error_stop);
+ }
+ check(pci_bar + REG_CTRL);
+ check(pci_bar + REG_STAT);
+#ifdef DEBUG_KERN
+ printk(KERN_INFO "END --- Error code %d", error);
+#endif
+
+ return error;
+}
+
+/**
+ * Wrapper of smbus_access access with PCA9548 I2C switch management.
+ * This function set PCA9548 switches to the proper slave channel.
+ * Only one channel among switches chip is selected during communication time.
+ *
+ * Note: If the bus does not have any PCA9548 on it, the switch_addr must be
+ * set to 0xFF, it will use normal smbus_access function.
+ */
+static int fpga_i2c_access(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char rw, u8 cmd,
+ int size, union i2c_smbus_data *data)
+{
+ int error, retval = 0;
+ struct i2c_dev_data *dev_data;
+ unsigned char master_bus;
+ unsigned char switch_addr;
+ unsigned char channel;
+ unsigned char *calling_name;
+ uint16_t prev_port = 0;
+ unsigned char prev_switch;
+ unsigned char prev_ch;
+ uint8_t read_channel;
+ int retry = 0;
+
+ dev_data = i2c_get_adapdata(adapter);
+ master_bus = dev_data->pca9548.master_bus;
+ switch_addr = dev_data->pca9548.switch_addr;
+ channel = dev_data->pca9548.channel;
+ calling_name = dev_data->pca9548.calling_name;
+
+ // Acquire the master resource.
+ mutex_lock(&fpga_i2c_master_locks[master_bus - 1]);
+ prev_port = fpga_i2c_lasted_access_port[master_bus - 1];
+ prev_switch = (unsigned char)(prev_port >> 8) & 0xFF;
+ prev_ch = (unsigned char)(prev_port & 0xFF);
+
+ if (switch_addr != 0xFF) {
+
+
+ // Check lasted access switch address on a master
+ // Only select new channel of a switch if they are difference from last channel of a switch
+ if ( prev_switch != switch_addr && prev_switch != 0 ) {
+ // reset prev_port PCA9548 chip
+ retry = 3;
+ while(retry--){
+ error = smbus_access(adapter, (u16)(prev_switch), flags, I2C_SMBUS_WRITE, 0x00, I2C_SMBUS_BYTE, NULL);
+ if(error >= 0){
+ break;
+ }else{
+ dev_dbg(&adapter->dev,"Failed to deselect ch %d of 0x%x, CODE %d\n", prev_ch, prev_switch, error);
+ }
+
+ }
+ if(retry < 0){
+ goto release_unlock;
+ }
+ // set PCA9548 to current channel
+ retry = 3;
+ while(retry--){
+ error = smbus_access(adapter, switch_addr, flags, I2C_SMBUS_WRITE, 1 << channel, I2C_SMBUS_BYTE, NULL);
+ if(error >= 0){
+ break;
+ }else{
+ dev_dbg(&adapter->dev,"Failed to select ch %d of 0x%x, CODE %d\n", prev_ch, prev_switch, error);
+ }
+
+ }
+ if(retry < 0){
+ goto release_unlock;
+ }
+ // update lasted port
+ fpga_i2c_lasted_access_port[master_bus - 1] = switch_addr << 8 | channel;
+
+ } else {
+ // check if channel is also changes
+ if ( prev_ch != channel || prev_switch == 0 ) {
+ // set new PCA9548 at switch_addr to current
+ retry = 3;
+ while(retry--){
+ error = smbus_access(adapter, switch_addr, flags, I2C_SMBUS_WRITE, 1 << channel, I2C_SMBUS_BYTE, NULL);
+ if(error >= 0){
+ break;
+ }else{
+ dev_dbg(&adapter->dev,"Failed to select ch %d of 0x%x, CODE %d\n", prev_ch, prev_switch, error);
+ }
+
+ }
+ if(retry < 0){
+ goto release_unlock;
+ }
+ // update lasted port
+ fpga_i2c_lasted_access_port[master_bus - 1] = switch_addr << 8 | channel;
+ }
+ }
+ }
+
+ // Do SMBus communication
+ nack_retry[master_bus - 1] = 0;
+ need_retry[master_bus - 1] = 0;
+ error = smbus_access(adapter, addr, flags, rw, cmd, size, data);
+ if((nack_retry[master_bus - 1]==1)&&(need_retry[master_bus - 1]==1))
+ retry = 2000;
+ else
+ retry = 5;
+ // If the first access failed, do retry.
+ while((nack_retry[master_bus - 1]==1)&&retry)
+ {
+ retry--;
+ nack_retry[master_bus - 1] = 0;
+ dev_dbg(&adapter->dev,"error = %d\n",error);
+ error = smbus_access(adapter, addr, flags, rw, cmd, size, data);
+ dev_dbg(&adapter->dev,"nack retry = %d\n",retry);
+ }
+ nack_retry[master_bus - 1] = 0;
+ need_retry[master_bus - 1] = 0;
+
+ retval = error;
+
+ if(error < 0){
+ dev_dbg( &adapter->dev,"smbus_xfer failed (%d) @ 0x%2.2X|f 0x%4.4X|(%d)%-5s| (%d)%-10s|CMD %2.2X "
+ , error, addr, flags, rw, rw == 1 ? "READ " : "WRITE"
+ , size, size == 0 ? "QUICK" :
+ size == 1 ? "BYTE" :
+ size == 2 ? "BYTE_DATA" :
+ size == 3 ? "WORD_DATA" :
+ size == 4 ? "PROC_CALL" :
+ size == 5 ? "BLOCK_DATA" :
+ size == 8 ? "I2C_BLOCK_DATA" : "ERROR"
+ , cmd);
+ }else{
+ goto release_unlock;
+ }
+
+ /** For the bus with PCA9548, try to read PCA9548 one more time.
+ * For the bus w/o PCA9548 just check the return from last time.
+ */
+ if (switch_addr != 0xFF) {
+ error = smbus_access(adapter, switch_addr, flags, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE, (union i2c_smbus_data*)&read_channel);
+ dev_dbg(&adapter->dev,"Try access I2C switch device at %2.2x\n", switch_addr);
+ if(error < 0){
+ dev_dbg(&adapter->dev,"Unbale to access switch device.\n");
+ }else{
+ dev_dbg(&adapter->dev,"Read success, register val %2.2x\n", read_channel);
+ }
+ }
+
+ // If retry was used up(retry = 0) and the last transfer result is -EBUSY
+ if(retry <= 0 && error == -EBUSY ){
+ retval = error;
+ // raise device error message
+ dev_err(&adapter->dev, "I2C bus hangup detected on %s port.\n", calling_name);
+
+ /**
+ * Phalanxp: Device specific I2C reset topology
+ */
+ if( master_bus == I2C_MASTER_CH_11 || master_bus == I2C_MASTER_CH_12 ||
+ master_bus == I2C_MASTER_CH_13 || master_bus == I2C_MASTER_CH_14 ){
+ dev_notice(&adapter->dev, "Trying bus recovery...\n");
+ dev_notice(&adapter->dev, "Reset I2C switch device.\n");
+
+ // reset PCA9548 on the current BUS.
+ if(master_bus == I2C_MASTER_CH_11){
+ // LC1_I2C3_RST_N .. LC1_I2C0_RST_N
+ iowrite8( ioread8(fpga_dev.data_base_addr + 0x0108) & 0xF0, fpga_dev.data_base_addr + 0x0108);
+ udelay(1);
+ iowrite8( ioread8(fpga_dev.data_base_addr + 0x0108) | 0x0F, fpga_dev.data_base_addr + 0x0108);
+ }else if(master_bus == I2C_MASTER_CH_12){
+ // LC1_I2C7_RST_N .. LC1_I2C4_RST_N
+ iowrite8( ioread8(fpga_dev.data_base_addr + 0x0108) & 0x8F, fpga_dev.data_base_addr + 0x0108);
+ udelay(1);
+ iowrite8( ioread8(fpga_dev.data_base_addr + 0x0108) | 0x70, fpga_dev.data_base_addr + 0x0108);
+ }else if(master_bus == I2C_MASTER_CH_13){
+ // LC2_I2C3_RST_N .. LC2_I2C0_RST_N
+ iowrite8( ioread8(fpga_dev.data_base_addr + 0x010c) & 0xF0, fpga_dev.data_base_addr + 0x010c);
+ udelay(1);
+ iowrite8( ioread8(fpga_dev.data_base_addr + 0x010c) | 0x0F, fpga_dev.data_base_addr + 0x010c);
+ }else if(master_bus == I2C_MASTER_CH_14){
+ // LC2_I2C7_RST_N .. LC2_I2C4_RST_N
+ iowrite8( ioread8(fpga_dev.data_base_addr + 0x010c) & 0x8F, fpga_dev.data_base_addr + 0x010c);
+ udelay(1);
+ iowrite8( ioread8(fpga_dev.data_base_addr + 0x010c) | 0x70, fpga_dev.data_base_addr + 0x010c);
+ }
+ // clear the last access port
+ fpga_i2c_lasted_access_port[master_bus - 1] = 0;
+ }else{
+ dev_crit(&adapter->dev, "I2C bus unrecoverable.\n");
+ }
+ }
+
+
+release_unlock:
+ mutex_unlock(&fpga_i2c_master_locks[master_bus - 1]);
+ dev_dbg(&adapter->dev,"switch ch %d of 0x%x -> ch %d of 0x%x\n", prev_ch, prev_switch, channel, switch_addr);
+ return retval;
+}
+
+/**
+ * A callback function show available smbus functions.
+ */
+static u32 fpga_i2c_func(struct i2c_adapter *a)
+{
+ return I2C_FUNC_SMBUS_QUICK |
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA|
+ I2C_FUNC_SMBUS_I2C_BLOCK;
+}
+
+static const struct i2c_algorithm phalanxp_i2c_algorithm = {
+ .smbus_xfer = fpga_i2c_access,
+ .functionality = fpga_i2c_func,
+};
+
+/**
+ * Create virtual I2C bus adapter for switch devices
+ * @param pdev platform device pointer
+ * @param portid virtual i2c port id for switch device mapping
+ * @param bus_number_offset bus offset for virtual i2c adapter in system
+ * @return i2c adapter.
+ *
+ * When bus_number_offset is -1, created adapter with dynamic bus number.
+ * Otherwise create adapter at i2c bus = bus_number_offset + portid.
+ */
+static struct i2c_adapter * phalanxp_i2c_init(struct platform_device *pdev, int portid, int bus_number_offset)
+{
+ int error;
+
+ struct i2c_adapter *new_adapter;
+ struct i2c_dev_data *new_data;
+
+ new_adapter = kzalloc(sizeof(*new_adapter), GFP_KERNEL);
+ if (!new_adapter) {
+ printk(KERN_ALERT "Cannot alloc i2c adapter for %s", fpga_i2c_bus_dev[portid].calling_name);
+ return NULL;
+ }
+
+ new_adapter->owner = THIS_MODULE;
+ new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ new_adapter->algo = &phalanxp_i2c_algorithm;
+ /* If the bus offset is -1, use dynamic bus number */
+ if (bus_number_offset == -1) {
+ new_adapter->nr = -1;
+ } else {
+ new_adapter->nr = bus_number_offset + portid;
+ }
+
+ new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
+ if (!new_data) {
+ printk(KERN_ALERT "Cannot alloc i2c data for %s", fpga_i2c_bus_dev[portid].calling_name);
+ kzfree(new_adapter);
+ return NULL;
+ }
+
+ new_data->portid = portid;
+ new_data->pca9548.master_bus = fpga_i2c_bus_dev[portid].master_bus;
+ new_data->pca9548.switch_addr = fpga_i2c_bus_dev[portid].switch_addr;
+ new_data->pca9548.channel = fpga_i2c_bus_dev[portid].channel;
+ strcpy(new_data->pca9548.calling_name, fpga_i2c_bus_dev[portid].calling_name);
+
+ snprintf(new_adapter->name, sizeof(new_adapter->name),
+ "SMBus I2C Adapter PortID: %s", new_data->pca9548.calling_name);
+
+ i2c_set_adapdata(new_adapter, new_data);
+ error = i2c_add_numbered_adapter(new_adapter);
+ if (error < 0) {
+ printk(KERN_ALERT "Cannot add i2c adapter %s", new_data->pca9548.calling_name);
+ kzfree(new_adapter);
+ kzfree(new_data);
+ return NULL;
+ }
+
+ return new_adapter;
+};
+
+// I/O resource need.
+static struct resource phalanxp_resources[] = {
+ {
+ .start = 0x10000000,
+ .end = 0x10001000,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static void phalanxp_dev_release( struct device * dev)
+{
+ return;
+}
+
+static struct platform_device phalanxp_dev = {
+ .name = DRIVER_NAME,
+ .id = -1,
+ .num_resources = ARRAY_SIZE(phalanxp_resources),
+ .resource = phalanxp_resources,
+ .dev = {
+ .release = phalanxp_dev_release,
+ }
+};
+
+/**
+ * Board info for QSFP/SFP+ eeprom.
+ * Note: Using OOM optoe as transceiver eeprom driver.
+ * https://www.opencompute.org/wiki/Networking/SpecsAndDesigns#Open_Optical_Monitoring
+ */
+static struct i2c_board_info sff8436_eeprom_info[] = {
+ { I2C_BOARD_INFO("optoe1", 0x50) }, //For QSFP w/ sff8436
+ { I2C_BOARD_INFO("optoe2", 0x50) }, //For SFP+ w/ sff8472
+};
+
+static int phalanxp_drv_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int ret = 0;
+ int portid_count;
+ uint8_t cpld1_version, cpld2_version, cpld3_version, cpld4_version;
+ uint16_t prev_i2c_switch = 0;
+ struct sff_device_data *sff_data;
+
+ /* The device class need to be instantiated before this function called */
+ BUG_ON(fpgafwclass == NULL);
+
+ fpga_data = devm_kzalloc(&pdev->dev, sizeof(struct phalanxp_fpga_data),
+ GFP_KERNEL);
+
+ if (!fpga_data)
+ return -ENOMEM;
+
+ // Set default read address to VERSION
+ fpga_data->fpga_read_addr = fpga_dev.data_base_addr + FPGA_VERSION;
+ fpga_data->cpld1_read_addr = 0x00;
+ fpga_data->cpld2_read_addr = 0x00;
+
+ mutex_init(&fpga_data->fpga_lock);
+ for (ret = I2C_MASTER_CH_1 ; ret <= I2C_MASTER_CH_TOTAL; ret++) {
+ mutex_init(&fpga_i2c_master_locks[ret - 1]);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (unlikely(!res)) {
+ printk(KERN_ERR "Specified Resource Not Available...\n");
+ kzfree(fpga_data);
+ return -1;
+ }
+
+ fpga = kobject_create_and_add("FPGA", &pdev->dev.kobj);
+ if (!fpga) {
+ kzfree(fpga_data);
+ return -ENOMEM;
+ }
+
+ ret = sysfs_create_group(fpga, &fpga_attr_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create FPGA sysfs attributes\n");
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ cpld1 = kobject_create_and_add("CPLD1", &pdev->dev.kobj);
+ if (!cpld1) {
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return -ENOMEM;
+ }
+ ret = sysfs_create_group(cpld1, &cpld1_attr_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create CPLD1 sysfs attributes\n");
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ cpld2 = kobject_create_and_add("CPLD2", &pdev->dev.kobj);
+ if (!cpld2) {
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return -ENOMEM;
+ }
+ ret = sysfs_create_group(cpld2, &cpld2_attr_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create CPLD2 sysfs attributes\n");
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ cpld3 = kobject_create_and_add("CPLD3", &pdev->dev.kobj);
+ if (!cpld3) {
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return -ENOMEM;
+ }
+ ret = sysfs_create_group(cpld3, &cpld3_attr_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create CPLD3 sysfs attributes\n");
+ kobject_put(cpld3);
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ cpld4 = kobject_create_and_add("CPLD4", &pdev->dev.kobj);
+ if (!cpld4) {
+ sysfs_remove_group(cpld3, &cpld3_attr_grp);
+ kobject_put(cpld3);
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return -ENOMEM;
+ }
+ ret = sysfs_create_group(cpld4, &cpld4_attr_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create CPLD4 sysfs attributes\n");
+ kobject_put(cpld4);
+ sysfs_remove_group(cpld3, &cpld3_attr_grp);
+ kobject_put(cpld3);
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ fancpld = kobject_create_and_add("FAN_CPLD", &pdev->dev.kobj);
+ if (!fancpld) {
+ sysfs_remove_group(cpld4, &cpld4_attr_grp);
+ kobject_put(cpld4);
+ sysfs_remove_group(cpld3, &cpld3_attr_grp);
+ kobject_put(cpld3);
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return -ENOMEM;
+ }
+ if(!allow_unsafe_i2c_access)
+ ret = sysfs_create_group(fancpld, &fancpld_no_attr_grp);
+ else
+ ret = sysfs_create_group(fancpld, &fancpld_attr_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create FAN_CPLD sysfs attributes\n");
+ kobject_put(fancpld);
+ sysfs_remove_group(cpld4, &cpld4_attr_grp);
+ kobject_put(cpld4);
+ sysfs_remove_group(cpld3, &cpld3_attr_grp);
+ kobject_put(cpld3);
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ sff_dev = device_create(fpgafwclass, NULL, MKDEV(0, 0), NULL, "sff_device");
+ if (IS_ERR(sff_dev)) {
+ printk(KERN_ERR "Failed to create sff device\n");
+ sysfs_remove_group(fancpld, &fancpld_attr_grp);
+ kobject_put(fancpld);
+ sysfs_remove_group(cpld4, &cpld4_attr_grp);
+ kobject_put(cpld4);
+ sysfs_remove_group(cpld3, &cpld3_attr_grp);
+ kobject_put(cpld3);
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return PTR_ERR(sff_dev);
+ }
+
+ ret = sysfs_create_group(&sff_dev->kobj, &sff_led_test_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create SFF attributes\n");
+ device_destroy(fpgafwclass, MKDEV(0, 0));
+ sysfs_remove_group(fancpld, &fancpld_attr_grp);
+ kobject_put(fancpld);
+ sysfs_remove_group(cpld4, &cpld4_attr_grp);
+ kobject_put(cpld4);
+ sysfs_remove_group(cpld3, &cpld3_attr_grp);
+ kobject_put(cpld3);
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ ret = sysfs_create_link(&pdev->dev.kobj, &sff_dev->kobj, "SFF");
+ if (ret != 0) {
+ sysfs_remove_group(&sff_dev->kobj, &sff_led_test_grp);
+ device_destroy(fpgafwclass, MKDEV(0, 0));
+ sysfs_remove_group(fancpld, &fancpld_attr_grp);
+ kobject_put(fancpld);
+ sysfs_remove_group(cpld4, &cpld4_attr_grp);
+ kobject_put(cpld4);
+ sysfs_remove_group(cpld3, &cpld3_attr_grp);
+ kobject_put(cpld3);
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ for (portid_count = I2C_MASTER_CH_1; portid_count <= I2C_MASTER_CH_TOTAL; portid_count++){
+
+ if(!allow_unsafe_i2c_access){
+ if( portid_count < I2C_MASTER_CH_7 ||
+ portid_count == I2C_MASTER_CH_9 || portid_count == I2C_MASTER_CH_10 )
+ continue;
+ }
+ ret = i2c_core_init(portid_count, I2C_DIV_100K, fpga_dev.data_base_addr);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Unable to init I2C core %d\n", portid_count);
+ sysfs_remove_group(&sff_dev->kobj, &sff_led_test_grp);
+ device_destroy(fpgafwclass, MKDEV(0, 0));
+ sysfs_remove_group(fancpld, &fancpld_attr_grp);
+ kobject_put(fancpld);
+ sysfs_remove_group(cpld4, &cpld4_attr_grp);
+ kobject_put(cpld4);
+ sysfs_remove_group(cpld3, &cpld3_attr_grp);
+ kobject_put(cpld3);
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+ }
+
+ for (portid_count = 0 ; portid_count < VIRTUAL_I2C_PORT_LENGTH ; portid_count++) {
+ if(!allow_unsafe_i2c_access){
+ if( portid_count >= FAN_I2C_CPLD_INDEX && portid_count < SW1_I2C_CPLD_INDEX ){
+ fpga_data->i2c_adapter[portid_count] = NULL;
+ continue;
+ }
+ }
+ fpga_data->i2c_adapter[portid_count] = phalanxp_i2c_init(pdev, portid_count, VIRTUAL_I2C_BUS_OFFSET);
+ }
+
+ /* Init SFF devices */
+ for (portid_count = 0; portid_count < SFF_PORT_TOTAL; portid_count++) {
+ struct i2c_adapter *i2c_adap = fpga_data->i2c_adapter[portid_count];
+ if (i2c_adap) {
+ fpga_data->sff_devices[portid_count] = phalanxp_sff_init(portid_count);
+ sff_data = dev_get_drvdata(fpga_data->sff_devices[portid_count]);
+ BUG_ON(sff_data == NULL);
+ if ( sff_data->port_type == QSFP ) {
+ fpga_data->sff_i2c_clients[portid_count] = i2c_new_device(i2c_adap, &sff8436_eeprom_info[0]);
+ } else {
+ fpga_data->sff_i2c_clients[portid_count] = i2c_new_device(i2c_adap, &sff8436_eeprom_info[1]);
+ }
+ sff_data = NULL;
+ sysfs_create_link(&fpga_data->sff_devices[portid_count]->kobj,
+ &fpga_data->sff_i2c_clients[portid_count]->dev.kobj,
+ "i2c");
+ }
+ }
+
+ printk(KERN_INFO "Virtual I2C buses created\n");
+
+#ifdef TEST_MODE
+ return 0;
+#endif
+ fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&cpld1_version);
+ fpga_i2c_access(fpga_data->i2c_adapter[SW1_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&cpld2_version);
+ fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&cpld3_version);
+ fpga_i2c_access(fpga_data->i2c_adapter[SW2_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&cpld4_version);
+
+ printk(KERN_INFO "Switch CPLD1 Version: %2.2x\n", cpld1_version);
+ printk(KERN_INFO "Switch CPLD2 Version: %2.2x\n", cpld2_version);
+ printk(KERN_INFO "Switch CPLD3 Version: %2.2x\n", cpld3_version);
+ printk(KERN_INFO "Switch CPLD4 Version: %2.2x\n", cpld4_version);
+
+
+ /* Init I2C buses that has PCA9548 switch device. */
+ for (portid_count = 0; portid_count < VIRTUAL_I2C_PORT_LENGTH; portid_count++) {
+
+ if(!allow_unsafe_i2c_access){
+ if( portid_count >= FAN_I2C_CPLD_INDEX && portid_count < SW1_I2C_CPLD_INDEX ){
+ continue;
+ }
+ }
+
+ struct i2c_dev_data *dev_data;
+ unsigned char master_bus;
+ unsigned char switch_addr;
+
+ dev_data = i2c_get_adapdata(fpga_data->i2c_adapter[portid_count]);
+ master_bus = dev_data->pca9548.master_bus;
+ switch_addr = dev_data->pca9548.switch_addr;
+
+ if (switch_addr != 0xFF) {
+
+ if (prev_i2c_switch != ( (master_bus << 8) | switch_addr) ) {
+ // Found the bus with PCA9548, trying to clear all switch in it.
+ smbus_access(fpga_data->i2c_adapter[portid_count], switch_addr, 0x00, I2C_SMBUS_WRITE, 0x00, I2C_SMBUS_BYTE, NULL);
+ prev_i2c_switch = ( master_bus << 8 ) | switch_addr;
+ }
+ }
+ }
+ return 0;
+}
+
+static int phalanxp_drv_remove(struct platform_device *pdev)
+{
+ int portid_count;
+ struct sff_device_data *rem_data;
+ struct i2c_dev_data *adap_data;
+
+ for (portid_count = 0; portid_count < SFF_PORT_TOTAL; portid_count++) {
+ sysfs_remove_link(&fpga_data->sff_devices[portid_count]->kobj, "i2c");
+ i2c_unregister_device(fpga_data->sff_i2c_clients[portid_count]);
+ }
+
+ for (portid_count = 0 ; portid_count < VIRTUAL_I2C_PORT_LENGTH ; portid_count++) {
+ if (fpga_data->i2c_adapter[portid_count] != NULL) {
+ info(KERN_INFO "<%x>", fpga_data->i2c_adapter[portid_count]);
+ adap_data = i2c_get_adapdata(fpga_data->i2c_adapter[portid_count]);
+ i2c_del_adapter(fpga_data->i2c_adapter[portid_count]);
+ }
+ }
+
+ for (portid_count = I2C_MASTER_CH_1; portid_count <= I2C_MASTER_CH_TOTAL; portid_count++){
+ if(!allow_unsafe_i2c_access){
+ if( portid_count < I2C_MASTER_CH_7 ||
+ portid_count == I2C_MASTER_CH_9 || portid_count == I2C_MASTER_CH_10 )
+ continue;
+ }
+ i2c_core_deinit(portid_count, fpga_dev.data_base_addr);
+ }
+
+ for (portid_count = 0; portid_count < SFF_PORT_TOTAL; portid_count++) {
+ if (fpga_data->sff_devices[portid_count] != NULL) {
+ rem_data = dev_get_drvdata(fpga_data->sff_devices[portid_count]);
+ device_unregister(fpga_data->sff_devices[portid_count]);
+ put_device(fpga_data->sff_devices[portid_count]);
+ kfree(rem_data);
+ }
+ }
+
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ sysfs_remove_group(cpld3, &cpld3_attr_grp);
+ sysfs_remove_group(cpld4, &cpld4_attr_grp);
+ sysfs_remove_group(fancpld, &fancpld_attr_grp);
+ sysfs_remove_group(&sff_dev->kobj, &sff_led_test_grp);
+ kobject_put(fpga);
+ kobject_put(cpld1);
+ kobject_put(cpld2);
+ kobject_put(cpld3);
+ kobject_put(cpld4);
+ kobject_put(fancpld);
+ device_destroy(fpgafwclass, MKDEV(0, 0));
+ devm_kfree(&pdev->dev, fpga_data);
+ return 0;
+}
+
+static struct platform_driver phalanxp_drv = {
+ .probe = phalanxp_drv_probe,
+ .remove = __exit_p(phalanxp_drv_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+};
+
+#ifdef TEST_MODE
+#define FPGA_PCI_BAR_NUM 2
+#else
+#define FPGA_PCI_BAR_NUM 0
+#endif
+
+
+
+static const struct pci_device_id fpga_id_table[] = {
+ { PCI_VDEVICE(XILINX, FPGA_PCIE_DEVICE_ID) },
+ { PCI_VDEVICE(TEST, TEST_PCIE_DEVICE_ID) },
+ {0, }
+};
+
+MODULE_DEVICE_TABLE(pci, fpga_id_table);
+
+static int fpga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ int err;
+ struct device *dev = &pdev->dev;
+ uint32_t fpga_version;
+
+ if ((err = pci_enable_device(pdev))) {
+ dev_err(dev, "pci_enable_device probe error %d for device %s\n",
+ err, pci_name(pdev));
+ return err;
+ }
+
+ if ((err = pci_request_regions(pdev, FPGA_PCI_NAME)) < 0) {
+ dev_err(dev, "pci_request_regions error %d\n", err);
+ goto pci_disable;
+ }
+
+ /* bar0: data mmio region */
+ fpga_dev.data_mmio_start = pci_resource_start(pdev, FPGA_PCI_BAR_NUM);
+ fpga_dev.data_mmio_len = pci_resource_len(pdev, FPGA_PCI_BAR_NUM);
+ fpga_dev.data_base_addr = ioremap_nocache(fpga_dev.data_mmio_start, fpga_dev.data_mmio_len);
+ if (!fpga_dev.data_base_addr) {
+ dev_err(dev, "cannot iomap region of size %lu\n",
+ (unsigned long)fpga_dev.data_mmio_len);
+ goto pci_release;
+ }
+ dev_info(dev, "data_mmio iomap base = 0x%lx \n",
+ (unsigned long)fpga_dev.data_base_addr);
+ dev_info(dev, "data_mmio_start = 0x%lx data_mmio_len = %lu\n",
+ (unsigned long)fpga_dev.data_mmio_start,
+ (unsigned long)fpga_dev.data_mmio_len);
+
+ printk(KERN_INFO "FPGA PCIe driver probe OK.\n");
+ printk(KERN_INFO "FPGA ioremap registers of size %lu\n", (unsigned long)fpga_dev.data_mmio_len);
+ printk(KERN_INFO "FPGA Virtual BAR %d at %8.8lx - %8.8lx\n", FPGA_PCI_BAR_NUM,
+ (unsigned long)fpga_dev.data_base_addr,
+ (unsigned long)(fpga_dev.data_base_addr + fpga_dev.data_mmio_len));
+ printk(KERN_INFO "");
+ fpga_version = ioread32(fpga_dev.data_base_addr);
+ printk(KERN_INFO "FPGA Version : %8.8x\n", fpga_version);
+ fpgafw_init();
+ platform_device_register(&phalanxp_dev);
+ platform_driver_register(&phalanxp_drv);
+ return 0;
+
+pci_release:
+ pci_release_regions(pdev);
+pci_disable:
+ pci_disable_device(pdev);
+ return -EBUSY;
+}
+
+static void fpga_pci_remove(struct pci_dev *pdev)
+{
+ platform_driver_unregister(&phalanxp_drv);
+ platform_device_unregister(&phalanxp_dev);
+ fpgafw_exit();
+ pci_iounmap(pdev, fpga_dev.data_base_addr);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ printk(KERN_INFO "FPGA PCIe driver remove OK.\n");
+};
+
+static struct pci_driver pci_dev_ops = {
+ .name = FPGA_PCI_NAME,
+ .probe = fpga_pci_probe,
+ .remove = fpga_pci_remove,
+ .id_table = fpga_id_table,
+};
+
+enum {
+ READREG,
+ WRITEREG
+};
+
+struct fpga_reg_data {
+ uint32_t addr;
+ uint32_t value;
+};
+
+static long fpgafw_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
+ int ret = 0;
+ struct fpga_reg_data data;
+ mutex_lock(&fpga_data->fpga_lock);
+
+#ifdef TEST_MODE
+ static uint32_t status_reg;
+#endif
+ // Switch function to read and write.
+ switch (cmd) {
+ case READREG:
+ if (copy_from_user(&data, (void __user*)arg, sizeof(data)) != 0) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EFAULT;
+ }
+ data.value = ioread32(fpga_dev.data_base_addr + data.addr);
+ if (copy_to_user((void __user*)arg , &data, sizeof(data)) != 0) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EFAULT;
+ }
+#ifdef TEST_MODE
+ if (data.addr == 0x1210) {
+ switch (status_reg) {
+ case 0x0000 : status_reg = 0x8000;
+ break;
+
+ case 0x8080 : status_reg = 0x80C0;
+ break;
+ case 0x80C0 : status_reg = 0x80F0;
+ break;
+ case 0x80F0 : status_reg = 0x80F8;
+ break;
+
+ }
+ iowrite32(status_reg, fpga_dev.data_base_addr + 0x1210);
+ }
+#endif
+
+
+ break;
+ case WRITEREG:
+ if (copy_from_user(&data, (void __user*)arg, sizeof(data)) != 0) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EFAULT;
+ }
+ iowrite32(data.value, fpga_dev.data_base_addr + data.addr);
+
+#ifdef TEST_MODE
+ if (data.addr == 0x1204) {
+ status_reg = 0x8080;
+ iowrite32(status_reg, fpga_dev.data_base_addr + 0x1210);
+ }
+#endif
+
+ break;
+ default:
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ mutex_unlock(&fpga_data->fpga_lock);
+ return ret;
+}
+
+
+const struct file_operations fpgafw_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = fpgafw_unlocked_ioctl,
+};
+
+
+static int fpgafw_init(void) {
+ printk(KERN_INFO "Initializing the switchboard driver\n");
+ // Try to dynamically allocate a major number for the device -- more difficult but worth it
+ majorNumber = register_chrdev(0, DEVICE_NAME, &fpgafw_fops);
+ if (majorNumber < 0) {
+ printk(KERN_ALERT "Failed to register a major number\n");
+ return majorNumber;
+ }
+ printk(KERN_INFO "Device registered correctly with major number %d\n", majorNumber);
+
+ // Register the device class
+ fpgafwclass = class_create(THIS_MODULE, CLASS_NAME);
+ if (IS_ERR(fpgafwclass)) { // Check for error and clean up if there is
+ unregister_chrdev(majorNumber, DEVICE_NAME);
+ printk(KERN_ALERT "Failed to register device class\n");
+ return PTR_ERR(fpgafwclass);
+ }
+ printk(KERN_INFO "Device class registered correctly\n");
+
+ // Register the device driver
+ fpgafwdev = device_create(fpgafwclass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
+ if (IS_ERR(fpgafwdev)) { // Clean up if there is an error
+ class_destroy(fpgafwclass); // Repeated code but the alternative is goto statements
+ unregister_chrdev(majorNumber, DEVICE_NAME);
+ printk(KERN_ALERT "Failed to create the FW upgrade device node\n");
+ return PTR_ERR(fpgafwdev);
+ }
+ printk(KERN_INFO "FPGA fw upgrade device node created correctly\n");
+ return 0;
+}
+
+static void fpgafw_exit(void) {
+ device_destroy(fpgafwclass, MKDEV(majorNumber, 0)); // remove the device
+ class_unregister(fpgafwclass); // unregister the device class
+ class_destroy(fpgafwclass); // remove the device class
+ unregister_chrdev(majorNumber, DEVICE_NAME); // unregister the major number
+ printk(KERN_INFO "Goodbye!\n");
+}
+
+int phalanxp_init(void)
+{
+ int rc;
+ rc = pci_register_driver(&pci_dev_ops);
+ if (rc)
+ return rc;
+ return 0;
+}
+
+void phalanxp_exit(void)
+{
+ pci_unregister_driver(&pci_dev_ops);
+}
+
+module_init(phalanxp_init);
+module_exit(phalanxp_exit);
+
+module_param(allow_unsafe_i2c_access, bool, 0400);
+MODULE_PARM_DESC(allow_unsafe_i2c_access, "enable i2c busses despite potential races against BMC bus access");
+
+MODULE_AUTHOR("Pradchaya P. ");
+MODULE_DESCRIPTION("Celestica phalanxp switchboard platform driver");
+MODULE_VERSION(MOD_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-cel/jaws/systemd/platform-modules-jaws.service b/platform/broadcom/sonic-platform-modules-cel/jaws/systemd/platform-modules-jaws.service
new file mode 100644
index 000000000000..a99d550e0f3c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/jaws/systemd/platform-modules-jaws.service
@@ -0,0 +1,14 @@
+
+[ Unit]
+Description=Celestica Jaws platform modules
+After=local-fs.target
+Before=pmon.service
+
+[Service]
+Type=oneshot
+ExecStart=-/etc/init.d/platform-modules-jaws start
+ExecStop=-/etc/init.d/platform-modules-jaws stop
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/__init__.py
new file mode 100644
index 000000000000..d82f3749319c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/__init__.py
@@ -0,0 +1,2 @@
+__all__ = ["platform", "chassis"]
+from sonic_platform import *
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/chassis.py
new file mode 100644
index 000000000000..dc622016cbb2
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/chassis.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Celestica
+#
+# Module contains an implementation of SONiC Platform Base API and
+# provides the Chassis information which are available in the platform
+#
+#############################################################################
+
+import sys
+import re
+import os
+import subprocess
+import json
+
+try:
+ from sonic_platform_base.chassis_base import ChassisBase
+ from sonic_platform.eeprom import Tlv
+ from sonic_platform.fan import Fan
+ from helper import APIHelper
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+NUM_FAN_TRAY = 7
+NUM_FAN = 2
+NUM_PSU = 2
+NUM_THERMAL = 5
+NUM_SFP = 32
+NUM_COMPONENT = 5
+
+IPMI_OEM_NETFN = "0x3A"
+IPMI_GET_REBOOT_CAUSE = "0x03 0x00 0x01 0x06"
+
+
+class Chassis(ChassisBase):
+ """Platform-specific Chassis class"""
+
+ def __init__(self):
+ self.config_data = {}
+ ChassisBase.__init__(self)
+ self._eeprom = Tlv()
+ self._api_helper = APIHelper()
+
+ for fant_index in range(0, NUM_FAN_TRAY):
+ for fan_index in range(0, NUM_FAN):
+ fan = Fan(fant_index, fan_index)
+ self._fan_list.append(fan)
+
+ def get_base_mac(self):
+ """
+ Retrieves the base MAC address for the chassis
+ Returns:
+ A string containing the MAC address in the format
+ 'XX:XX:XX:XX:XX:XX'
+ """
+ return self._eeprom.get_mac()
+
+ def get_serial_number(self):
+ """
+ Retrieves the hardware serial number for the chassis
+ Returns:
+ A string containing the hardware serial number for this chassis.
+ """
+ return self._eeprom.get_serial()
+
+ def get_system_eeprom_info(self):
+ """
+ Retrieves the full content of system EEPROM information for the chassis
+ Returns:
+ A dictionary where keys are the type code defined in
+ OCP ONIE TlvInfo EEPROM format and values are their corresponding
+ values.
+ """
+ return self._eeprom.get_eeprom()
+
+ def get_reboot_cause(self):
+ """
+ Retrieves the cause of the previous reboot
+
+ Returns:
+ A tuple (string, string) where the first element is a string
+ containing the cause of the previous reboot. This string must be
+ one of the predefined strings in this class. If the first string
+ is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
+ to pass a description of the reboot cause.
+ """
+
+ status, raw_cause = self._api_helper.ipmi_raw(
+ IPMI_OEM_NETFN, IPMI_GET_REBOOT_CAUSE)
+ hx_cause = raw_cause.split()[0] if status else 00
+ reboot_cause = {
+ "00": self.REBOOT_CAUSE_HARDWARE_OTHER,
+ "11": self.REBOOT_CAUSE_POWER_LOSS,
+ "22": self.REBOOT_CAUSE_NON_HARDWARE,
+ "33": self.REBOOT_CAUSE_HARDWARE_OTHER,
+ "44": self.REBOOT_CAUSE_NON_HARDWARE,
+ "55": self.REBOOT_CAUSE_NON_HARDWARE,
+ "66": self.REBOOT_CAUSE_WATCHDOG,
+ "77": self.REBOOT_CAUSE_NON_HARDWARE
+ }.get(hx_cause, self.REBOOT_CAUSE_HARDWARE_OTHER)
+
+ description = {
+ "00": "Unknown reason",
+ "11": "The last reset is Power on reset",
+ "22": "The last reset is soft-set CPU warm reset",
+ "33": "The last reset is soft-set CPU cold reset",
+ "44": "The last reset is CPU warm reset",
+ "55": "The last reset is CPU cold reset",
+ "66": "The last reset is watchdog reset",
+ "77": "The last reset is power cycle reset"
+ }.get(hx_cause, "Unknown reason")
+
+ return (reboot_cause, description)
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/eeprom.py
new file mode 100644
index 000000000000..dd0c9332b54e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/eeprom.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Celestica Silverstone
+#
+# Platform and model specific eeprom subclass, inherits from the base class,
+# and provides the followings:
+# - the eeprom format definition
+# - specific encoder/decoder if there is special need
+#############################################################################
+
+try:
+ import glob
+ import os
+ import sys
+ import imp
+ import re
+ from array import array
+ from cStringIO import StringIO
+ from sonic_platform_base.sonic_eeprom import eeprom_dts
+ from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo
+except ImportError, e:
+ raise ImportError(str(e) + "- required module not found")
+
+CACHE_ROOT = '/var/cache/sonic/decode-syseeprom'
+CACHE_FILE = 'syseeprom_cache'
+TLV_EEPROM_I2C_BUS = 0
+TLV_EEPROM_I2C_ADDR = 56
+
+class Tlv(eeprom_tlvinfo.TlvInfoDecoder):
+
+ EEPROM_DECODE_HEADLINES = 6
+
+ def __init__(self):
+ self._eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-00{1}/eeprom".format(TLV_EEPROM_I2C_BUS, TLV_EEPROM_I2C_ADDR)
+ super(Tlv, self).__init__(self._eeprom_path, 0, '', True)
+ self._eeprom = self._load_eeprom()
+
+ def __parse_output(self, decode_output):
+ decode_output.replace('\0', '')
+ lines = decode_output.split('\n')
+ lines = lines[self.EEPROM_DECODE_HEADLINES:]
+ _eeprom_info_dict = dict()
+
+ for line in lines:
+ try:
+ match = re.search(
+ '(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+)', line)
+ if match is not None:
+ idx = match.group(1)
+ value = match.group(3).rstrip('\0')
+
+ _eeprom_info_dict[idx] = value
+ except:
+ pass
+ return _eeprom_info_dict
+
+ def _load_eeprom(self):
+ original_stdout = sys.stdout
+ sys.stdout = StringIO()
+ try:
+ self.read_eeprom_db()
+ except:
+ decode_output = sys.stdout.getvalue()
+ sys.stdout = original_stdout
+ return self.__parse_output(decode_output)
+
+ status = self.check_status()
+ if 'ok' not in status:
+ return False
+
+ if not os.path.exists(CACHE_ROOT):
+ try:
+ os.makedirs(CACHE_ROOT)
+ except:
+ pass
+
+ #
+ # only the eeprom classes that inherit from eeprom_base
+ # support caching. Others will work normally
+ #
+ try:
+ self.set_cache_name(os.path.join(CACHE_ROOT, CACHE_FILE))
+ except:
+ pass
+
+ e = self.read_eeprom()
+ if e is None:
+ return 0
+
+ try:
+ self.update_cache(e)
+ except:
+ pass
+
+ self.decode_eeprom(e)
+ decode_output = sys.stdout.getvalue()
+ sys.stdout = original_stdout
+
+ (is_valid, valid_crc) = self.is_checksum_valid(e)
+ if not is_valid:
+ return False
+
+ return self.__parse_output(decode_output)
+
+ def get_eeprom(self):
+ return self._eeprom
+
+ def get_serial(self):
+ return self._eeprom.get('0x23', "Undefined.")
+
+ def get_mac(self):
+ return self._eeprom.get('0x24', "Undefined.")
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/fan.py
new file mode 100644
index 000000000000..902de261f8cb
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/fan.py
@@ -0,0 +1,276 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Celestica
+#
+# Module contains an implementation of SONiC Platform Base API and
+# provides the fan status which are available in the platform
+#
+#############################################################################
+
+import json
+import math
+import os.path
+
+try:
+ from sonic_platform_base.fan_base import FanBase
+ from helper import APIHelper
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+
+FAN_NAME_LIST = ["FAN-1F", "FAN-1R", "FAN-2F", "FAN-2R", "FAN-3F", "FAN-3R",
+ "FAN-4F", "FAN-4R", "FAN-5F", "FAN-5R", "FAN-6F", "FAN-6R", "FAN-7F", "FAN-7R"]
+
+IPMI_OEM_NETFN = "0x3A"
+IPMI_SENSOR_NETFN = "0x04"
+IPMI_FAN_SPEED_CMD = "0x2D {}"
+IPMI_AIR_FLOW_CMD = "0x0A {}"
+IPMI_FAN_PRESENT_CMD = "0x06 0x03 {}"
+IPMI_SET_FAN_LED_CMD = "0x07 {} {}"
+IPMI_GET_FAN_LED_CMD = "0x08 {}"
+IPMI_SET_PWM = "0x03 0x01 0x02 {} {}"
+IPMI_FRU_PRINT_ID = "ipmitool fru print {}"
+IPMI_FRU_MODEL_KEY = "Board Part Number"
+IPMI_FRU_SERIAL_KEY = "Board Serial"
+
+MAX_OUTLET = 24700
+MAX_INLET = 29700
+SPEED_TOLERANCE = 10
+
+FAN1_FRONT_SS_ID = "0x0D"
+FAN1_REAR_SS_ID = "0x45"
+FAN_LED_OFF_CMD = "0x00"
+FAN_LED_GREEN_CMD = "0x01"
+FAN_LED_RED_CMD = "0x02"
+FAN1_LED_CMD = "0x04"
+FAN_PWM_REGISTER_START = 0x22
+FAN_PWM_REGISTER_STEP = 0x10
+FAN1_FRU_ID = 6
+
+
+class Fan(FanBase):
+ """Platform-specific Fan class"""
+
+ def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0):
+ self.fan_index = fan_index
+ self.fan_tray_index = fan_tray_index
+ self.is_psu_fan = is_psu_fan
+ if self.is_psu_fan:
+ self.psu_index = psu_index
+ self._api_helper = APIHelper()
+ self.index = self.fan_tray_index * 2 + self.fan_index
+
+ def get_direction(self):
+ """
+ Retrieves the direction of fan
+ Returns:
+ A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
+ depending on fan direction
+ """
+ direction = self.FAN_DIRECTION_EXHAUST
+ status, raw_flow = self._api_helper.ipmi_raw(
+ IPMI_OEM_NETFN, IPMI_AIR_FLOW_CMD.format(hex(self.fan_tray_index)))
+ if status and raw_flow == "01":
+ direction = self.FAN_DIRECTION_INTAKE
+
+ return direction
+
+ def get_speed(self):
+ """
+ Retrieves the speed of fan as a percentage of full speed
+ Returns:
+ An integer, the percentage of full fan speed, in the range 0 (off)
+ to 100 (full speed)
+
+ Note:
+ M = 150
+ Max F2B = 24700 RPM
+ Max B2F = 29700 RPM
+ """
+ # ipmitool raw 0x3a 0x03 0x01 0x01 {register}
+ # register = 22 32 42 52 62 72 82
+
+ max_rpm = MAX_OUTLET if self.fan_index % 2 == 0 else MAX_INLET
+ fan1_ss_start = FAN1_FRONT_SS_ID if self.fan_index % 2 == 0 else FAN1_REAR_SS_ID
+
+ ss_id = hex(int(fan1_ss_start, 16) + self.fan_tray_index)
+ status, raw_ss_read = self._api_helper.ipmi_raw(
+ IPMI_SENSOR_NETFN, IPMI_FAN_SPEED_CMD.format(ss_id))
+
+ ss_read = raw_ss_read.split()[0]
+ rpm_speed = int(ss_read, 16)*150
+ speed = int(float(rpm_speed)/max_rpm * 100)
+
+ return speed
+
+ def get_target_speed(self):
+ """
+ Retrieves the target (expected) speed of the fan
+ Returns:
+ An integer, the percentage of full fan speed, in the range 0 (off)
+ to 100 (full speed)
+
+ Note:
+ speed_pc = pwm_target/255*100
+
+ 0 : when PWM mode is use
+ pwm : when pwm mode is not use
+ """
+ target = 0
+ return target
+
+ def get_speed_tolerance(self):
+ """
+ Retrieves the speed tolerance of the fan
+ Returns:
+ An integer, the percentage of variance from target speed which is
+ considered tolerable
+ """
+ return SPEED_TOLERANCE
+
+ def set_speed(self, speed):
+ """
+ Sets the fan speed
+ Args:
+ speed: An integer, the percentage of full fan speed to set fan to,
+ in the range 0 (off) to 100 (full speed)
+ Returns:
+ A boolean, True if speed is set successfully, False if not
+ Notes:
+ pwm setting mode must set as Manual
+ manual: ipmitool raw 0x3a 0x06 0x01 0x0
+ auto: ipmitool raw 0x3a 0x06 0x01 0x1
+ """
+ # ipmitool raw 0x3a 0x03 0x01 0x02 {register} {pwm_speed}
+ # register = 22 32 42 52 62 72 82
+
+ speed_hex = hex(int(float(speed)/100 * 255))
+ fan_register_hex = hex(FAN_PWM_REGISTER_START +
+ (self.fan_tray_index*FAN_PWM_REGISTER_STEP))
+
+ set_speed_cmd = IPMI_SET_PWM.format(fan_register_hex, speed_hex)
+ status, set_speed_res = self._api_helper.ipmi_raw(
+ IPMI_OEM_NETFN, set_speed_cmd)
+
+ set_speed = False if not status else True
+
+ return set_speed
+
+ def set_status_led(self, color):
+ """
+ Sets the state of the fan module status LED
+ Args:
+ color: A string representing the color with which to set the
+ fan module status LED
+ Returns:
+ bool: True if status LED state is set successfully, False if not
+
+ Note:
+ LED setting mode must set as Manual
+ manual: ipmitool raw 0x3A 0x09 0x02 0x00
+ auto: ipmitool raw 0x3A 0x09 0x02 0x01
+ """
+ led_cmd = {
+ self.STATUS_LED_COLOR_GREEN: FAN_LED_GREEN_CMD,
+ self.STATUS_LED_COLOR_RED: FAN_LED_RED_CMD,
+ self.STATUS_LED_COLOR_OFF: FAN_LED_OFF_CMD
+ }.get(color)
+
+ fan_selector = hex(int(FAN1_LED_CMD, 16) + self.fan_tray_index)
+ status, set_led = self._api_helper.ipmi_raw(
+ IPMI_OEM_NETFN, IPMI_SET_FAN_LED_CMD.format(fan_selector, led_cmd))
+ set_status_led = False if not status else True
+
+ return set_status_led
+
+ def get_status_led(self):
+ """
+ Gets the state of the fan status LED
+ Returns:
+ A string, one of the predefined STATUS_LED_COLOR_* strings above
+
+ Note:
+ STATUS_LED_COLOR_GREEN = "green"
+ STATUS_LED_COLOR_AMBER = "amber"
+ STATUS_LED_COLOR_RED = "red"
+ STATUS_LED_COLOR_OFF = "off"
+ """
+ fan_selector = hex(int(FAN1_LED_CMD, 16) + self.fan_tray_index)
+ status, hx_color = self._api_helper.ipmi_raw(
+ IPMI_OEM_NETFN, IPMI_GET_FAN_LED_CMD.format(fan_selector))
+
+ status_led = {
+ "00": self.STATUS_LED_COLOR_OFF,
+ "01": self.STATUS_LED_COLOR_GREEN,
+ "02": self.STATUS_LED_COLOR_RED,
+ }.get(hx_color, self.STATUS_LED_COLOR_OFF)
+
+ return status_led
+
+ def get_name(self):
+ """
+ Retrieves the name of the device
+ Returns:
+ string: The name of the device
+ """
+ fan_name = FAN_NAME_LIST[self.fan_tray_index*2 + self.fan_index] if not self.is_psu_fan else "PSU-{} FAN-{}".format(
+ self.psu_index+1, self.fan_index+1)
+
+ return fan_name
+
+ def get_presence(self):
+ """
+ Retrieves the presence of the FAN
+ Returns:
+ bool: True if FAN is present, False if not
+ """
+ presence = False
+ status, raw_present = self._api_helper.ipmi_raw(
+ IPMI_OEM_NETFN, IPMI_FAN_PRESENT_CMD.format(hex(self.index)))
+ if status and raw_present == "00":
+ presence = True
+
+ return presence
+
+ def get_model(self):
+ """
+ Retrieves the model number (or part number) of the device
+ Returns:
+ string: Model/part number of device
+ """
+ model = "Unknown"
+ ipmi_fru_idx = self.fan_tray_index + FAN1_FRU_ID
+ status, raw_model = self._api_helper.ipmi_fru_id(
+ ipmi_fru_idx, IPMI_FRU_MODEL_KEY)
+
+ fru_pn_list = raw_model.split()
+ if len(fru_pn_list) > 4:
+ model = fru_pn_list[4]
+
+ return model
+
+ def get_serial(self):
+ """
+ Retrieves the serial number of the device
+ Returns:
+ string: Serial number of device
+ """
+ serial = "Unknown"
+ ipmi_fru_idx = self.fan_tray_index + FAN1_FRU_ID
+ status, raw_model = self._api_helper.ipmi_fru_id(
+ ipmi_fru_idx, IPMI_FRU_SERIAL_KEY)
+
+ fru_sr_list = raw_model.split()
+ if len(fru_sr_list) > 3:
+ serial = fru_sr_list[3]
+
+ return serial
+
+ def get_status(self):
+ """
+ Retrieves the operational status of the device
+ Returns:
+ A boolean value, True if device is operating properly, False if not
+ """
+ return self.get_presence() and self.get_speed() > 0
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/helper.py b/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/helper.py
new file mode 100644
index 000000000000..1132b5b06785
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/helper.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+
+import os
+import subprocess
+
+
+HOST_CHK_CMD = "docker > /dev/null 2>&1"
+EMPTY_STRING = ""
+
+
+class APIHelper():
+
+ def __init__(self):
+ pass
+
+ def is_host(self):
+ return os.system(HOST_CHK_CMD) == 0
+
+ def read_txt_file(self, file_path):
+ try:
+ with open(file_path, 'r') as fd:
+ data = fd.read()
+ return data.strip()
+ except IOError:
+ pass
+ return None
+
+ def ipmi_raw(self, netfn, cmd):
+ status = True
+ result = ""
+ try:
+ cmd = "ipmitool raw {} {}".format(str(netfn), str(cmd))
+ p = subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ raw_data, err = p.communicate()
+ if err == '':
+ result = raw_data.strip()
+ except:
+ status = False
+ return status, result
+
+ def ipmi_fru_id(self, id, key=None):
+ status = True
+ result = ""
+ try:
+ cmd = "ipmitool fru print {}".format(str(
+ id)) if not key else "ipmitool fru print {0} | grep '{1}' ".format(str(id), str(key))
+
+ p = subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ raw_data, err = p.communicate()
+ if err == '':
+ result = raw_data.strip()
+ except:
+ status = False
+ return status, result
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/platform.py
new file mode 100644
index 000000000000..a632de87e742
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/build/lib.linux-x86_64-2.7/sonic_platform/platform.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Celestica
+#
+# Module contains an implementation of SONiC Platform Base API and
+# provides the platform information
+#
+#############################################################################
+
+try:
+ from sonic_platform_base.platform_base import PlatformBase
+ from sonic_platform.chassis import Chassis
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+
+class Platform(PlatformBase):
+ """Platform-specific Platform class"""
+
+ def __init__(self):
+ PlatformBase.__init__(self)
+ self._chassis = Chassis()
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/cfg/shamu-modules.conf b/platform/broadcom/sonic-platform-modules-cel/shamu/cfg/shamu-modules.conf
new file mode 100644
index 000000000000..66f002a5fc94
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/cfg/shamu-modules.conf
@@ -0,0 +1,15 @@
+# /etc/modules: kernel modules to load at boot time.
+#
+# This file contains the names of kernel modules that should be loaded
+# at boot time, one per line. Lines beginning with "#" are ignored.
+
+i2c-i801
+i2c-isch
+i2c-ismt
+i2c-dev
+i2c-mux
+i2c-smbus
+
+i2c-mux-gpio
+i2c-mux-pca954x
+
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/Makefile
new file mode 100644
index 000000000000..99b818ea21fb
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/Makefile
@@ -0,0 +1 @@
+obj-m := mc24lc64t.o baseboard_cpld.o switchboard_fpga.o dimm-bus.o i2c-imc.o
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/modules/baseboard_cpld.c b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/baseboard_cpld.c
new file mode 100644
index 000000000000..a4dfed2ac18a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/baseboard_cpld.c
@@ -0,0 +1,409 @@
+/*
+ * baseboard_cpld.c - driver for Fishbone2 Base Board CPLD
+ * This driver implement sysfs for CPLD register access using LPC bus.
+ * Copyright (C) 2018 Celestica Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRIVER_NAME "AS1440D.cpldb"
+/**
+ * CPLD register address for read and write.
+ */
+#define VERSION_ADDR 0xA100
+#define SCRATCH_ADDR 0xA101
+#define SYS_LED_ADDR 0xA162
+
+#define CPLD_REGISTER_SIZE 0x77
+
+struct baseboard_cpld_data {
+ struct mutex cpld_lock;
+ uint16_t read_addr;
+};
+
+struct baseboard_cpld_data *cpld_data;
+
+/**
+ * Read the value from scratch register as hex string.
+ * @param dev kernel device
+ * @param devattr kernel device attribute
+ * @param buf buffer for get value
+ * @return Hex string read from scratch register.
+ */
+static ssize_t scratch_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ unsigned char data = 0;
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SCRATCH_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return sprintf(buf,"0x%2.2x\n", data);
+}
+
+/**
+ * Set scratch register with specific hex string.
+ * @param dev kernel device
+ * @param devattr kernel device attribute
+ * @param buf buffer of set value
+ * @param count number of bytes in buffer
+ * @return number of bytes written, or error code < 0.
+ */
+static ssize_t scratch_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ char *last;
+
+ mutex_lock(&cpld_data->cpld_lock);
+ data = (uint16_t)strtoul(buf,&last,16);
+ if(data == 0 && buf == last){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+ outb(data, SCRATCH_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return count;
+}
+static DEVICE_ATTR_RW(scratch);
+
+
+/* CPLD version attributes */
+static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ mutex_lock(&cpld_data->cpld_lock);
+ int len = sprintf(buf, "0x%2.2x\n",inb(VERSION_ADDR));
+ mutex_unlock(&cpld_data->cpld_lock);
+ return len;
+}
+static DEVICE_ATTR_RO(version);
+
+
+static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ // CPLD register is one byte
+ uint16_t addr;
+ char *last;
+
+ addr = (uint16_t)strtoul(buf,&last,16);
+ if(addr == 0 && buf == last){
+ return -EINVAL;
+ }
+ cpld_data->read_addr = addr;
+ return count;
+}
+
+static ssize_t getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ mutex_lock(&cpld_data->cpld_lock);
+ int len = sprintf(buf, "0x%2.2x\n",inb(cpld_data->read_addr));
+ mutex_unlock(&cpld_data->cpld_lock);
+ return len;
+}
+static DEVICE_ATTR_RW(getreg);
+
+static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ // CPLD register is one byte
+ uint16_t addr;
+ uint8_t value;
+ char *tok;
+ char clone[count];
+ char *pclone = clone;
+ char *last;
+
+ strcpy(clone, buf);
+
+ mutex_lock(&cpld_data->cpld_lock);
+ tok = strsep((char**)&pclone, " ");
+ if(tok == NULL){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+ addr = (uint16_t)strtoul(tok,&last,16);
+ if(addr == 0 && tok == last){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+
+ tok = strsep((char**)&pclone, " ");
+ if(tok == NULL){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+ value = (uint8_t)strtoul(tok,&last,16);
+ if(value == 0 && tok == last){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+
+ outb(value,addr);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return count;
+}
+static DEVICE_ATTR_WO(setreg);
+
+/**
+ * Read all CPLD register in binary mode.
+ * @return number of byte read.
+ */
+static ssize_t dump_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t off, size_t count)
+{
+ unsigned long i=0;
+ ssize_t status;
+
+ mutex_lock(&cpld_data->cpld_lock);
+begin:
+ if(i < count){
+ buf[i++] = inb(VERSION_ADDR + off);
+ off++;
+ msleep(1);
+ goto begin;
+ }
+ status = count;
+exit:
+ mutex_unlock(&cpld_data->cpld_lock);
+ return status;
+}
+static BIN_ATTR_RO(dump, CPLD_REGISTER_SIZE);
+
+/**
+ * Show system led status - on/off/1k/4k
+ * @param dev kernel device
+ * @param devattr kernel device attribute
+ * @param buf buffer for get value
+ * @return Hex string read from scratch register.
+ */
+static ssize_t sys_led_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ unsigned char data = 0;
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SYS_LED_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ data = data & 0x3;
+ return sprintf(buf, "%s\n",
+ data == 0x03 ? "off" : data == 0x02 ? "4k" : data ==0x01 ? "1k": "on");
+}
+
+/**
+ * Set the status of system led - on/off/1k/4k
+ * @param dev kernel device
+ * @param devattr kernel device attribute
+ * @param buf buffer of set value
+ * @param count number of bytes in buffer
+ * @return number of bytes written, or error code < 0.
+ */
+static ssize_t sys_led_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ unsigned char led_status,data;
+ if(sysfs_streq(buf, "off")){
+ led_status = 0x03;
+ }else if(sysfs_streq(buf, "4k")){
+ led_status = 0x02;
+ }else if(sysfs_streq(buf, "1k")){
+ led_status = 0x01;
+ }else if(sysfs_streq(buf, "on")){
+ led_status = 0x00;
+ }else{
+ count = -EINVAL;
+ return count;
+ }
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SYS_LED_ADDR);
+ data = data & ~(0x3);
+ data = data | led_status;
+ outb(data, SYS_LED_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return count;
+}
+static DEVICE_ATTR_RW(sys_led);
+
+/**
+ * Show system led color - both/green/yellow/none
+ * @param dev kernel device
+ * @param devattr kernel device attribute
+ * @param buf buffer for get value
+ * @return Hex string read from scratch register.
+ */
+static ssize_t sys_led_color_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ unsigned char data = 0;
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SYS_LED_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ data = (data >> 4) & 0x3;
+ return sprintf(buf, "%s\n",
+ data == 0x03 ? "off" : data == 0x02 ? "yellow" : data ==0x01 ? "green": "both");
+}
+
+/**
+ * Set the color of system led - both/green/yellow/none
+ * @param dev kernel device
+ * @param devattr kernel device attribute
+ * @param buf buffer of set value
+ * @param count number of bytes in buffer
+ * @return number of bytes written, or error code < 0.
+ */
+static ssize_t sys_led_color_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ unsigned char led_status,data;
+ if(sysfs_streq(buf, "off")){
+ led_status = 0x03;
+ }else if(sysfs_streq(buf, "yellow")){
+ led_status = 0x02;
+ }else if(sysfs_streq(buf, "green")){
+ led_status = 0x01;
+ }else if(sysfs_streq(buf, "both")){
+ led_status = 0x00;
+ }else{
+ count = -EINVAL;
+ return count;
+ }
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SYS_LED_ADDR);
+ data = data & ~( 0x3 << 4);
+ data = data | (led_status << 4);
+ outb(data, SYS_LED_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return count;
+}
+static DEVICE_ATTR_RW(sys_led_color);
+
+static struct attribute *baseboard_cpld_attrs[] = {
+ &dev_attr_version.attr,
+ &dev_attr_scratch.attr,
+ &dev_attr_getreg.attr,
+ &dev_attr_setreg.attr,
+ &dev_attr_sys_led.attr,
+ &dev_attr_sys_led_color.attr,
+ NULL,
+};
+
+static struct bin_attribute *baseboard_cpld_bin_attrs[] = {
+ &bin_attr_dump,
+ NULL,
+};
+
+static struct attribute_group baseboard_cpld_attrs_grp = {
+ .attrs = baseboard_cpld_attrs,
+ .bin_attrs = baseboard_cpld_bin_attrs,
+};
+
+static struct resource baseboard_cpld_resources[] = {
+ {
+ .start = 0xA100,
+ .end = 0xA1FF,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static void baseboard_cpld_dev_release( struct device * dev)
+{
+ return;
+}
+
+static struct platform_device baseboard_cpld_dev = {
+ .name = DRIVER_NAME,
+ .id = -1,
+ .num_resources = ARRAY_SIZE(baseboard_cpld_resources),
+ .resource = baseboard_cpld_resources,
+ .dev = {
+ .release = baseboard_cpld_dev_release,
+ }
+};
+
+static int baseboard_cpld_drv_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int ret =0;
+ int portid_count;
+
+ cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct baseboard_cpld_data),
+ GFP_KERNEL);
+ if (!cpld_data)
+ return -ENOMEM;
+
+ mutex_init(&cpld_data->cpld_lock);
+
+ cpld_data->read_addr = VERSION_ADDR;
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (unlikely(!res)) {
+ printk(KERN_ERR "Specified Resource Not Available...\n");
+ return -1;
+ }
+
+ ret = sysfs_create_group(&pdev->dev.kobj, &baseboard_cpld_attrs_grp);
+ if (ret) {
+ printk(KERN_ERR "Cannot create sysfs for baseboard CPLD\n");
+ }
+ return 0;
+}
+
+static int baseboard_cpld_drv_remove(struct platform_device *pdev)
+{
+ sysfs_remove_group(&pdev->dev.kobj, &baseboard_cpld_attrs_grp);
+ return 0;
+}
+
+static struct platform_driver baseboard_cpld_drv = {
+ .probe = baseboard_cpld_drv_probe,
+ .remove = __exit_p(baseboard_cpld_drv_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+};
+
+int baseboard_cpld_init(void)
+{
+ // Register platform device and platform driver
+ platform_device_register(&baseboard_cpld_dev);
+ platform_driver_register(&baseboard_cpld_drv);
+ return 0;
+}
+
+void baseboard_cpld_exit(void)
+{
+ // Unregister platform device and platform driver
+ platform_driver_unregister(&baseboard_cpld_drv);
+ platform_device_unregister(&baseboard_cpld_dev);
+}
+
+module_init(baseboard_cpld_init);
+module_exit(baseboard_cpld_exit);
+
+MODULE_AUTHOR("Pradchaya Phucharoen ");
+MODULE_DESCRIPTION("Celestica Fishbone2 Baseboard CPLD Driver");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/modules/dimm-bus.c b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/dimm-bus.c
new file mode 100644
index 000000000000..9f30945e1d1c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/dimm-bus.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013-2016 Andrew Lutomirski
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include
+#include
+#include
+#include "dimm-bus.h"
+static bool probe_addr(struct i2c_adapter *adapter, int addr)
+{
+ /*
+ * So far, all known devices that live on DIMMs can be safely
+ * and reliably detected by trying to read a byte at address
+ * zero. (The exception is the SPD write protection control,
+ * which can't be probed and requires special hardware and/or
+ * quick writes to access, and has no driver.)
+ */
+ union i2c_smbus_data dummy;
+ return i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_READ, 0,
+ I2C_SMBUS_BYTE_DATA, &dummy) >= 0;
+}
+/**
+ * i2c_scan_dimm_bus() - Scans an SMBUS segment known to contain DIMMs
+ * @adapter: The SMBUS adapter to scan
+ *
+ * This function tells the DIMM-bus code that the adapter is known to
+ * contain DIMMs. i2c_scan_dimm_bus will probe for devices known to
+ * live on DIMMs.
+ *
+ * Do NOT call this function on general-purpose system SMBUS segments
+ * unless you know that the only things on the bus are DIMMs.
+ * Otherwise is it very likely to mis-identify other things on the
+ * bus.
+ *
+ * Callers are advised not to set adapter->class = I2C_CLASS_SPD to
+ * avoid having two separate mechanisms trying to automatically claim
+ * devices on the bus.
+ */
+void i2c_scan_dimm_bus(struct i2c_adapter *adapter)
+{
+ struct i2c_board_info info = {};
+ int slot;
+ /*
+ * We probe with "read byte data". If any DIMM SMBUS driver can't
+ * support that access type, this function should be updated.
+ */
+ if (WARN_ON(!i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_READ_BYTE_DATA)))
+ return;
+ /*
+ * Addresses on DIMMs use the three low bits to identify the slot
+ * and the four high bits to identify the device type. Known
+ * devices include:
+ *
+ * - 0x10 - 0x17: NVDIMM controller (pre-standard)
+ * - 0x18 - 0x1f: TSOD (Temperature Sensor on DIMM)
+ * - 0x40 - 0x47: JESD245 Byte Addressable Energy Backed Interface
+ * - 0x50 - 0x57: SPD (Serial Presence Detect) EEPROM
+ * - 0x30 - 0x37: SPD WP control -- not easy to probe
+ *
+ * There's no point in trying to probe the SPD WP control: we'd
+ * want to probe using quick reads, which i2c-imc doesn't
+ * support, we don't have a driver for it, we can't really use
+ * it without special hardware (it's not a normal i2c slave --
+ * see the JEDEC docs), and using it risks bricking the DIMM
+ * it's on anyway.
+ *
+ * NB: There's no need to save the return value from
+ * i2c_new_device, as the core code will unregister it for us
+ * when the adapter is removed. If users want to bind a
+ * different driver, nothing stops them from unbinding the
+ * drivers we request here.
+ */
+ for (slot = 0; slot < 8; slot++) {
+ /* If there's no SPD, then assume there's no DIMM here. */
+ if (!probe_addr(adapter, 0x50 | slot))
+ continue;
+ strcpy(info.type, "ee1004");
+ info.addr = 0x50 | slot;
+ i2c_new_device(adapter, &info);
+ if (probe_addr(adapter, 0x18 | slot)) {
+ /*
+ * This is a temperature sensor. The interface is
+ * defined in the JEDEC TSE2004av specification.
+ * Linux's driver for this is called "jc42", which
+ * is a bit nonsensical (JC-42 is the name of the
+ * committee, not the sensor).
+ */
+ strcpy(info.type, "jc42");
+ info.addr = 0x18 | slot;
+ i2c_new_device(adapter, &info);
+ }
+ }
+}
+EXPORT_SYMBOL(i2c_scan_dimm_bus);
+MODULE_AUTHOR("Andrew Lutomirski ");
+MODULE_DESCRIPTION("i2c DIMM bus support");
+MODULE_LICENSE("GPL v2");
+
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/modules/dimm-bus.h b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/dimm-bus.h
new file mode 100644
index 000000000000..8f14d5fb973f
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/dimm-bus.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2013-2016 Andrew Lutomirski
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef _I2C_DIMM_BUS
+#define _I2C_DIMM_BUS
+struct i2c_adapter;
+void i2c_scan_dimm_bus(struct i2c_adapter *adapter);
+#endif /* _I2C_DIMM_BUS */
+
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/modules/i2c-imc.c b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/i2c-imc.c
new file mode 100644
index 000000000000..7b053f43916e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/i2c-imc.c
@@ -0,0 +1,556 @@
+/*
+ * Copyright (c) 2013-2016 Andrew Lutomirski
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "dimm-bus.h"
+
+/*
+ * The datasheet can be found here, for example:
+ * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e5-1600-2600-vol-2-datasheet.pdf
+ *
+ * There seem to be quite a few bugs or spec errors, though:
+ *
+ * - A successful transaction sets WOD and RDO.
+ *
+ * - The docs for TSOD_POLL_EN make no sense (see imc_channel_claim).
+ *
+ * - Erratum BT109, which says:
+ *
+ * The processor may not complete SMBus (System Management Bus)
+ * transactions targeting the TSOD (Temperature Sensor On DIMM)
+ * when Package C-States are enabled. Due to this erratum, if the
+ * processor transitions into a Package C-State while an SMBus
+ * transaction with the TSOD is in process, the processor will
+ * suspend receipt of the transaction. The transaction completes
+ * while the processor is in a Package C-State. Upon exiting
+ * Package C-State, the processor will attempt to resume the
+ * SMBus transaction, detect a protocol violation, and log an
+ * error.
+ *
+ * The description notwithstanding, I've seen difficult-to-reproduce
+ * issues when the system goes completely idle (so package C-states can
+ * be entered) while software-initiated SMBUS transactions are in
+ * progress.
+ */
+
+/* Register offsets (in PCI configuration space) */
+#define SMBSTAT(i) (0x180 + 0x10*(i))
+#define SMBCMD(i) (0x184 + 0x10*(i))
+#define SMBCNTL(i) (0x188 + 0x10*(i))
+#define SMB_TSOD_POLL_RATE_CNTR(i) (0x18C + 0x10*(i))
+#define SMB_TSOD_POLL_RATE (0x1A8)
+
+/* SMBSTAT fields */
+#define SMBSTAT_RDO (1U << 31) /* Read Data Valid */
+#define SMBSTAT_WOD (1U << 30) /* Write Operation Done */
+#define SMBSTAT_SBE (1U << 29) /* SMBus Error */
+#define SMBSTAT_SMB_BUSY (1U << 28) /* SMBus Busy State */
+/* 26:24 is the last automatically polled TSOD address */
+#define SMBSTAT_RDATA_MASK 0xffff /* result of a read */
+
+/* SMBCMD fields */
+#define SMBCMD_TRIGGER (1U << 31) /* CMD Trigger */
+#define SMBCMD_PNTR_SEL (1U << 30) /* HW polls TSOD with pointer */
+#define SMBCMD_WORD_ACCESS (1U << 29) /* word (vs byte) access */
+#define SMBCMD_TYPE_MASK (3U << 27) /* Mask for access type */
+#define SMBCMD_TYPE_READ (0U << 27) /* Read */
+#define SMBCMD_TYPE_WRITE (1U << 27) /* Write */
+#define SMBCMD_TYPE_PNTR_WRITE (3U << 27) /* Write to pointer */
+#define SMBCMD_SA_MASK (7U << 24) /* Slave Address high bits */
+#define SMBCMD_SA_SHIFT 24
+#define SMBCMD_BA_MASK 0xff0000 /* Bus Txn address */
+#define SMBCMD_BA_SHIFT 16
+#define SMBCMD_WDATA_MASK 0xffff /* data to write */
+
+/* SMBCNTL fields */
+#define SMBCNTL_DTI_MASK 0xf0000000 /* Slave Address low bits */
+#define SMBCNTL_DTI_SHIFT 28 /* Slave Address low bits */
+#define SMBCNTL_CKOVRD (1U << 27) /* # Clock Override */
+#define SMBCNTL_DIS_WRT (1U << 26) /* Disable Write (sadly) */
+#define SMBCNTL_SOFT_RST (1U << 10) /* Soft Reset */
+#define SMBCNTL_TSOD_POLL_EN (1U << 8) /* TSOD Polling Enable */
+/* Bits 0-3 and 4-6 indicate TSOD presence in various slots */
+
+/* Bits that might randomly change if we race with something. */
+#define SMBCMD_OUR_BITS (~(u32)SMBCMD_TRIGGER)
+#define SMBCNTL_OUR_BITS (SMBCNTL_DTI_MASK | SMBCNTL_TSOD_POLL_EN)
+
+/* System Address Controller, PCI dev 13 fn 6, 8086.3cf5 */
+#define SAD_CONTROL 0xf4
+
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_BR 0x3cf5 /* 13.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA 0x3ca8 /* 15.0 */
+
+#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA 0x6fa8
+#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM 0x6f71
+#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA 0x6f68
+#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM 0x6f79
+
+static atomic_t imc_raced; /* Set permanently to 1 if we screw up. */
+
+static bool allow_unsafe_access;
+
+struct imc_channel {
+ struct i2c_adapter adapter;
+ struct mutex mutex; /* protects access to regs and prev_tsod_poll */
+ bool can_write, suspended;
+ bool prev_tsod_poll;
+};
+
+struct imc_priv {
+ struct pci_dev *pci_dev;
+ struct imc_channel channels[2];
+};
+
+static bool imc_wait_not_busy(struct imc_priv *priv, int chan, u32 *stat)
+{
+ /*
+ * The clock is around 100kHz, and transactions are nine cycles
+ * per byte plus a few start/stop cycles, plus whatever clock
+ * streching is involved. This means that polling every 70us
+ * or so will give decent performance.
+ *
+ * Ideally we would calculate a good estimate for the
+ * transaction time and sleep, but busy-waiting is an effective
+ * workaround for an apparent Sandy Bridge bug that causes bogus
+ * output if the system enters a package C-state. (NB: these
+ * states are systemwide -- we don't need be running on the
+ * right package for this to work.)
+ *
+ * When Ivy Bridge and Haswell support are added, we could
+ * consider making the busy-wait depend on the platform.
+ */
+
+ int i;
+
+ for (i = 0; i < 50; i++) {
+ pci_read_config_dword(priv->pci_dev, SMBSTAT(chan), stat);
+ if (!(*stat & SMBSTAT_SMB_BUSY))
+ return true;
+ udelay(70); /* see comment above -- we need to busy-wait */
+ }
+
+ return false;
+}
+
+static void imc_channel_release(struct imc_priv *priv, int chan)
+{
+ /* Return to HW control. */
+ if (priv->channels[chan].prev_tsod_poll) {
+ u32 cntl;
+
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+ cntl |= SMBCNTL_TSOD_POLL_EN;
+ pci_write_config_dword(priv->pci_dev, SMBCNTL(chan), cntl);
+ }
+}
+
+static int imc_channel_claim(struct imc_priv *priv, int chan)
+{
+ /*
+ * The docs are a bit confused here. We're supposed to disable TSOD
+ * polling, then wait for busy to be cleared, then set
+ * SMBCNTL_TSOD_POLL_EN to zero to switch to software control. But
+ * SMBCNTL_TSOD_POLL_EN is the only documented way to turn off polling.
+ */
+
+ u32 cntl, stat;
+
+ if (priv->channels[chan].suspended)
+ return -EIO;
+
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+ priv->channels[chan].prev_tsod_poll = !!(cntl & SMBCNTL_TSOD_POLL_EN);
+ cntl &= ~SMBCNTL_TSOD_POLL_EN;
+ pci_write_config_dword(priv->pci_dev, SMBCNTL(chan), cntl);
+
+ /* Sometimes the hardware won't let go. */
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+ if (cntl & SMBCNTL_TSOD_POLL_EN)
+ return -EBUSY;
+
+ if (!imc_wait_not_busy(priv, chan, &stat)) {
+ imc_channel_release(priv, chan);
+ return -EBUSY; /* Someone else is controlling the bus. */
+ }
+
+ return 0; /* The channel is ours. */
+}
+
+static bool imc_channel_can_claim(struct imc_priv *priv, int chan)
+{
+ u32 orig_cntl, cntl;
+
+ /* See if we can turn off TSOD_POLL_EN. */
+
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &orig_cntl);
+ pci_write_config_dword(priv->pci_dev, SMBCNTL(chan),
+ orig_cntl & ~SMBCNTL_TSOD_POLL_EN);
+
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+ if (cntl & SMBCNTL_TSOD_POLL_EN)
+ return false; /* Failed. */
+
+ pci_write_config_dword(priv->pci_dev, SMBCNTL(chan), orig_cntl);
+ return true;
+}
+
+/*
+ * The iMC supports five access types. The terminology is rather
+ * inconsistent. These are the types:
+ *
+ * "Write to pointer register SMBus": I2C_SMBUS_WRITE, I2C_SMBUS_BYTE
+ *
+ * Read byte/word: I2C_SMBUS_READ, I2C_SMBUS_{BYTE|WORD}_DATA
+ *
+ * Write byte/word: I2C_SMBUS_WRITE, I2C_SMBUS_{BYTE|WORD}_DATA
+ *
+ * The pointer write operations is AFAICT completely useless for
+ * software control, for two reasons. First, HW periodically polls any
+ * TSODs on the bus, so it will corrupt the pointer in between SW
+ * transactions. More importantly, the matching "read byte"/"receive
+ * byte" (the address-less single-byte read) is not available for SW
+ * control. Therefore, this driver doesn't implement pointer writes
+ *
+ * There is no PEC support.
+ */
+
+static u32 imc_func(struct i2c_adapter *adapter)
+{
+ int chan;
+ struct imc_channel *ch;
+ struct imc_priv *priv = i2c_get_adapdata(adapter);
+
+ chan = (adapter == &priv->channels[0].adapter ? 0 : 1);
+ ch = &priv->channels[chan];
+
+ if (ch->can_write)
+ return I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
+ else
+ return I2C_FUNC_SMBUS_READ_BYTE_DATA |
+ I2C_FUNC_SMBUS_READ_WORD_DATA;
+}
+
+static s32 imc_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+ unsigned short flags, char read_write, u8 command,
+ int size, union i2c_smbus_data *data)
+{
+ int ret, chan;
+ u32 cmd = 0, cntl, final_cmd, final_cntl, stat;
+ struct imc_channel *ch;
+ struct imc_priv *priv = i2c_get_adapdata(adap);
+
+ if (atomic_read(&imc_raced))
+ return -EIO; /* Minimize damage. */
+
+ chan = (adap == &priv->channels[0].adapter ? 0 : 1);
+ ch = &priv->channels[chan];
+
+ /* Encode CMD part of addresses and access size */
+ cmd |= ((u32)addr & 0x7) << SMBCMD_SA_SHIFT;
+ cmd |= ((u32)command) << SMBCMD_BA_SHIFT;
+ if (size == I2C_SMBUS_WORD_DATA)
+ cmd |= SMBCMD_WORD_ACCESS;
+
+ /* Encode read/write and data to write */
+ if (read_write == I2C_SMBUS_READ) {
+ cmd |= SMBCMD_TYPE_READ;
+ } else {
+ cmd |= SMBCMD_TYPE_WRITE;
+ cmd |= (size == I2C_SMBUS_WORD_DATA
+ ? swab16(data->word)
+ : data->byte);
+ }
+
+ mutex_lock(&ch->mutex);
+
+ ret = imc_channel_claim(priv, chan);
+ if (ret)
+ goto out_unlock;
+
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+ cntl &= ~SMBCNTL_DTI_MASK;
+ cntl |= ((u32)addr >> 3) << SMBCNTL_DTI_SHIFT;
+ pci_write_config_dword(priv->pci_dev, SMBCNTL(chan), cntl);
+
+ /*
+ * This clears SMBCMD_PNTR_SEL. We leave it cleared so that we don't
+ * need to think about keeping the TSOD pointer state consistent with
+ * the hardware's expectation. This probably has some miniscule
+ * power cost, as TSOD polls will take 9 extra cycles.
+ */
+ cmd |= SMBCMD_TRIGGER;
+ pci_write_config_dword(priv->pci_dev, SMBCMD(chan), cmd);
+
+ if (!imc_wait_not_busy(priv, chan, &stat)) {
+ /* Timeout. TODO: Reset the controller? */
+ ret = -ETIMEDOUT;
+ dev_dbg(&priv->pci_dev->dev, "controller is wedged\n");
+ goto out_release;
+ }
+
+ /*
+ * Be paranoid: try to detect races. This will only detect races
+ * against BIOS, not against hardware. (I've never seen this happen.)
+ */
+ pci_read_config_dword(priv->pci_dev, SMBCMD(chan), &final_cmd);
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &final_cntl);
+ if (((cmd ^ final_cmd) & SMBCMD_OUR_BITS) ||
+ ((cntl ^ final_cntl) & SMBCNTL_OUR_BITS)) {
+ WARN(1, "iMC SMBUS raced against firmware");
+ dev_err(&priv->pci_dev->dev,
+ "Access to channel %d raced: cmd 0x%08X->0x%08X, cntl 0x%08X->0x%08X\n",
+ chan, cmd, final_cmd, cntl, final_cntl);
+ atomic_set(&imc_raced, 1);
+ ret = -EIO;
+ goto out_release;
+ }
+
+ if (stat & SMBSTAT_SBE) {
+ /*
+ * Clear the error to re-enable TSOD polling. The docs say
+ * that, as long as SBE is set, TSOD polling won't happen.
+ * The docs also say that writing zero to this bit (which is
+ * the only writable bit in the whole register) will clear
+ * the error. Empirically, writing 0 does not clear SBE, but
+ * it's probably still good to do the write in compliance with
+ * the spec. (TSOD polling still happens and seems to
+ * clear SBE on its own.)
+ */
+ pci_write_config_dword(priv->pci_dev, SMBSTAT(chan), 0);
+ ret = -ENXIO;
+ goto out_release;
+ }
+
+ if (read_write == I2C_SMBUS_READ) {
+ if (!(stat & SMBSTAT_RDO)) {
+ dev_dbg(&priv->pci_dev->dev,
+ "Unexpected read status 0x%08X\n", stat);
+ ret = -EIO;
+ goto out_release;
+ }
+
+ /*
+ * The iMC SMBUS controller thinks of SMBUS words as
+ * being big-endian (MSB first). Linux treats them as
+ * little-endian, so we need to swap them.
+ *
+ * Note: the controller will often (always?) set WOD
+ * here. This is probably a hardware bug.
+ */
+ if (size == I2C_SMBUS_WORD_DATA)
+ data->word = swab16(stat & SMBSTAT_RDATA_MASK);
+ else
+ data->byte = stat & 0xFF;
+ } else {
+ /*
+ * Note: the controller will often (always?) set RDO here.
+ * This is probably a hardware bug.
+ */
+ if (!(stat & SMBSTAT_WOD)) {
+ dev_dbg(&priv->pci_dev->dev,
+ "Unexpected write status 0x%08X\n", stat);
+ ret = -EIO;
+ }
+ }
+
+out_release:
+ imc_channel_release(priv, chan);
+
+out_unlock:
+ mutex_unlock(&ch->mutex);
+
+ return ret;
+}
+
+static const struct i2c_algorithm imc_smbus_algorithm = {
+ .smbus_xfer = imc_smbus_xfer,
+ .functionality = imc_func,
+};
+
+static int imc_init_channel(struct imc_priv *priv, int i, int socket)
+{
+ int err;
+ u32 val;
+ struct imc_channel *ch = &priv->channels[i];
+
+ /*
+ * With CLTT enabled, the hardware won't let us turn
+ * off TSOD polling. The device is completely useless
+ * when this happens (at least without help from Intel),
+ * but we can at least minimize confusion.
+ */
+ if (!imc_channel_can_claim(priv, i)) {
+ dev_warn(&priv->pci_dev->dev,
+ "iMC channel %d: we cannot control the HW. Is CLTT on?\n",
+ i);
+ return -EBUSY;
+ }
+
+ i2c_set_adapdata(&ch->adapter, priv);
+ ch->adapter.owner = THIS_MODULE;
+ ch->adapter.algo = &imc_smbus_algorithm;
+ ch->adapter.dev.parent = &priv->pci_dev->dev;
+
+ pci_read_config_dword(priv->pci_dev, SMBCNTL(i), &val);
+ ch->can_write = !(val & SMBCNTL_DIS_WRT);
+
+ mutex_init(&ch->mutex);
+
+ snprintf(ch->adapter.name, sizeof(ch->adapter.name),
+ "iMC socket %d channel %d", socket, i);
+ err = i2c_add_adapter(&ch->adapter);
+ if (err) {
+ mutex_destroy(&ch->mutex);
+ return err;
+ }
+
+ i2c_scan_dimm_bus(&ch->adapter);
+
+ return 0;
+}
+
+static void imc_free_channel(struct imc_priv *priv, int i)
+{
+ struct imc_channel *ch = &priv->channels[i];
+
+ i2c_del_adapter(&ch->adapter);
+ mutex_destroy(&ch->mutex);
+}
+
+static struct pci_dev *imc_get_related_device(struct pci_bus *bus,
+ unsigned int devfn, u16 devid)
+{
+ struct pci_dev *dev = pci_get_slot(bus, devfn);
+
+ if (!dev)
+ return NULL;
+ if (dev->vendor != PCI_VENDOR_ID_INTEL || dev->device != devid) {
+ pci_dev_put(dev);
+ return NULL;
+ }
+ return dev;
+}
+
+static int imc_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ int i, j, err;
+ struct imc_priv *priv;
+
+ priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ priv->pci_dev = dev;
+
+ pci_set_drvdata(dev, priv);
+
+ for (i = 0; i < 1; i++) {
+ err = imc_init_channel(priv, i, 0);
+ if (err)
+ goto exit_free_channels;
+ printk(KERN_INFO "IMC: Create IMC SMBus OK.\n");
+ }
+
+ return 0;
+
+exit_free_channels:
+ printk(KERN_INFO "IMC: Free chennel I2C.\n");
+ for (j = 0; j < i; j++)
+ imc_free_channel(priv, j);
+ return err;
+}
+
+static void imc_remove(struct pci_dev *dev)
+{
+ int i;
+ struct imc_priv *priv = pci_get_drvdata(dev);
+
+ for (i = 0; i < 1; i++)
+ imc_free_channel(priv, i);
+}
+
+static int imc_suspend(struct pci_dev *dev, pm_message_t mesg)
+{
+ int i;
+ struct imc_priv *priv = pci_get_drvdata(dev);
+
+ /* BIOS is in charge. We should finish any pending transaction */
+ for (i = 0; i < 1; i++) {
+ mutex_lock(&priv->channels[i].mutex);
+ priv->channels[i].suspended = true;
+ mutex_unlock(&priv->channels[i].mutex);
+ }
+
+ return 0;
+}
+
+static int imc_resume(struct pci_dev *dev)
+{
+ int i;
+ struct imc_priv *priv = pci_get_drvdata(dev);
+
+ for (i = 0; i < 1; i++) {
+ mutex_lock(&priv->channels[i].mutex);
+ priv->channels[i].suspended = false;
+ mutex_unlock(&priv->channels[i].mutex);
+ }
+
+ return 0;
+}
+
+static const struct pci_device_id imc_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA) },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, imc_ids);
+
+static struct pci_driver imc_pci_driver = {
+ .name = "imc_smbus",
+ .id_table = imc_ids,
+ .probe = imc_probe,
+ .remove = imc_remove,
+ .suspend = imc_suspend,
+ .resume = imc_resume,
+};
+
+static int __init i2c_imc_init(void)
+{
+ if (!allow_unsafe_access)
+ return -ENODEV;
+
+ pr_warn("using this driver is dangerous unless your firmware is specifically designed for it; use at your own risk\n");
+ return pci_register_driver(&imc_pci_driver);
+}
+module_init(i2c_imc_init);
+
+static void __exit i2c_imc_exit(void)
+{
+ pci_unregister_driver(&imc_pci_driver);
+}
+module_exit(i2c_imc_exit);
+
+module_param(allow_unsafe_access, bool, 0400);
+MODULE_PARM_DESC(allow_unsafe_access, "enable i2c_imc despite potential races against BIOS/hardware bus access");
+
+MODULE_AUTHOR("Andrew Lutomirski ");
+MODULE_DESCRIPTION("iMC SMBus driver");
+MODULE_LICENSE("GPL v2");
+
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/mc24lc64t.c
new file mode 100644
index 000000000000..ae79770a4d8e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/mc24lc64t.c
@@ -0,0 +1,173 @@
+/*
+ * mc24lc64t.c - driver for Microchip 24LC64T
+ *
+ * Copyright (C) 2017 Celestica Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define EEPROM_SIZE 8192 //mc24lt64t eeprom size in bytes.
+
+struct mc24lc64t_data {
+ struct mutex update_lock;
+};
+
+static ssize_t mc24lc64t_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client = kobj_to_i2c_client(kobj);
+ struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
+ unsigned long timeout, read_time, i = 0;
+ int status;
+
+ mutex_lock(&drvdata->update_lock);
+
+ if (i2c_smbus_write_byte_data(client, off>>8, off))
+ {
+ status = -EIO;
+ goto exit;
+ }
+
+ msleep(1);
+
+begin:
+
+ if (i < count)
+ {
+ timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/
+ do {
+ read_time = jiffies;
+
+ status = i2c_smbus_read_byte(client);
+ if (status >= 0)
+ {
+ buf[i++] = status;
+ goto begin;
+ }
+ } while (time_before(read_time, timeout));
+
+ status = -ETIMEDOUT;
+ goto exit;
+ }
+
+ status = count;
+
+exit:
+ mutex_unlock(&drvdata->update_lock);
+
+ return status;
+}
+
+static ssize_t mc24lc64t_write (struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count){
+
+ struct i2c_client *client = kobj_to_i2c_client(kobj);
+ struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
+ unsigned long timeout, write_time, i = 0;
+ int status;
+ u16 value;
+
+ mutex_lock(&drvdata->update_lock);
+
+begin:
+ if (i < count){
+ timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/
+ value = (buf[i] << 8)| off;
+ do {
+ write_time = jiffies;
+ status = i2c_smbus_write_word_data(client, off>>8, value);
+ if (status >= 0)
+ {
+ // increase offset
+ off++;
+ // increase buffer index
+ i++;
+ goto begin;
+ }
+ } while (time_before(write_time, timeout));
+ status = -ETIMEDOUT;
+ goto exit;
+ }
+ status = count;
+
+exit:
+ mutex_unlock(&drvdata->update_lock);
+ return status;
+}
+
+static struct bin_attribute mc24lc64t_bit_attr = {
+ .attr = {
+ .name = "eeprom",
+ .mode = S_IRUGO | S_IWUGO,
+ },
+ .size = EEPROM_SIZE,
+ .read = mc24lc64t_read,
+ .write = mc24lc64t_write,
+};
+
+static int mc24lc64t_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ struct mc24lc64t_data *drvdata;
+ int err;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
+ | I2C_FUNC_SMBUS_READ_BYTE))
+ return -EPFNOSUPPORT;
+
+ if (!(drvdata = devm_kzalloc(&client->dev,
+ sizeof(struct mc24lc64t_data), GFP_KERNEL)))
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, drvdata);
+ mutex_init(&drvdata->update_lock);
+
+ err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr);
+
+ return err;
+}
+
+static int mc24lc64t_remove(struct i2c_client *client)
+{
+ struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
+ sysfs_remove_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr);
+
+ return 0;
+}
+
+static const struct i2c_device_id mc24lc64t_id[] = {
+ { "24lc64t", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mc24lc64t_id);
+
+static struct i2c_driver mc24lc64t_driver = {
+ .driver = {
+ .name = "mc24lc64t",
+ .owner = THIS_MODULE,
+ },
+ .probe = mc24lc64t_probe,
+ .remove = mc24lc64t_remove,
+ .id_table = mc24lc64t_id,
+};
+
+module_i2c_driver(mc24lc64t_driver);
+
+MODULE_AUTHOR("Abhisit Sangjan ");
+MODULE_DESCRIPTION("Microchip 24LC64T Driver");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/modules/sonic_platform-1.0-py2-none-any.whl b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/sonic_platform-1.0-py2-none-any.whl
new file mode 100644
index 000000000000..75d574b5a123
Binary files /dev/null and b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/sonic_platform-1.0-py2-none-any.whl differ
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/modules/switchboard_fpga.c b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/switchboard_fpga.c
new file mode 100644
index 000000000000..e537eb7955c3
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/modules/switchboard_fpga.c
@@ -0,0 +1,2431 @@
+/*
+ * switchboard_fpga.c - Driver for Fishbone2 Switch board FPGA/CPLD.
+ *
+ * Author: Pradchaya Phucharoen
+ *
+ * Copyright (C) 2018 Celestica Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * /
+ * \--sys
+ * \--devices
+ * \--platform
+ * \--AS1440DF.switchboard
+ * |--FPGA
+ * |--CPLD1
+ * |--CPLD2
+ * \--SFF
+ * \--QSFP[1..32]
+ *
+ */
+
+#ifndef TEST_MODE
+#define MOD_VERSION "0.5.2"
+#else
+#define MOD_VERSION "TEST"
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static int majorNumber;
+
+#define CLASS_NAME "fishbone2_fpga"
+#define DRIVER_NAME "AS1440D.switchboard"
+#define FPGA_PCI_NAME "fishbone2_fpga_pci"
+#define DEVICE_NAME "fwupgrade"
+
+static bool allow_unsafe_i2c_access;
+
+static int smbus_access(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char rw, u8 cmd,
+ int size, union i2c_smbus_data *data);
+
+static int fpga_i2c_access(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char rw, u8 cmd,
+ int size, union i2c_smbus_data *data);
+
+static int i2c_core_init(unsigned int master_bus, unsigned int freq_div,void __iomem *pci_bar);
+static void i2c_core_deinit(unsigned int master_bus, void __iomem *pci_bar);
+static int i2c_xcvr_access(u8 register_address, unsigned int portid, u8 *data, char rw);
+
+static int fpgafw_init(void);
+static void fpgafw_exit(void);
+
+/*
+========================================
+FPGA PCIe BAR 0 Registers
+========================================
+Misc Control 0x00000000 – 0x000000FF
+I2C_CH1 0x00000800 - 0x0000081C
+I2C_CH2 0x00000820 - 0x0000083C
+I2C_CH3 0x00000840 - 0x0000085C
+I2C_CH4 0x00000860 - 0x0000087C
+I2C_CH5 0x00000880 - 0x0000089C
+I2C_CH6 0x000008A0 - 0x000008BC
+I2C_CH7 0x000008C0 - 0x000008DC
+I2C_CH8 0x000008E0 - 0x000008FC
+I2C_CH9 0x00000900 - 0x0000091C
+I2C_CH10 0x00000920 - 0x0000093C
+I2C_CH11 0x00000940 - 0x0000095C
+I2C_CH12 0x00000960 - 0x0000097C
+I2C_CH13 0x00000980 - 0x0000099C
+I2C_CH14 0x000009A0 - 0x000009BC
+SPI Master 0x00000A00 - 0x00000BFC
+PORT XCVR 0x00004000 - 0x00004FFF
+*/
+
+/* MISC */
+#define FPGA_VERSION 0x0000
+#define FPGA_VERSION_MJ_MSK 0xff00
+#define FPGA_VERSION_MN_MSK 0x00ff
+#define FPGA_SCRATCH 0x0004
+#define FPGA_BROAD_TYPE 0x0008
+#define BMC_I2C_SCRATCH 0x0020
+#define FPGA_SLAVE_CPLD_REST 0x0100
+#define FPGA_SWITCH_RESET_CTRL 0x0104
+#define FPAG_PRH_RESER_CTRL 0x0108
+#define FPGA_INT_STATUS 0x0200
+#define FPGA_INT_SRC_STATUS 0x0204
+#define FPGA_INT_FLAG 0x0208
+#define FPGA_INT_MASK 0x020c
+#define FPGA_MISC_CTRL 0x0300
+#define FPGA_MISC_STATUS 0x0304
+
+/* I2C_MASTER BASE ADDR */
+#define I2C_MASTER_FREQ_L 0x0800
+#define I2C_MASTER_FREQ_H 0x0804
+#define I2C_MASTER_CTRL 0x0808
+#define I2C_MASTER_DATA 0x080c
+#define I2C_MASTER_CMD 0x0810 /* Write-Only Register */
+#define I2C_MASTER_STATUS 0x0810 /* Read-Only Register */
+#define I2C_MASTER_CH_1 1
+#define I2C_MASTER_CH_2 2
+#define I2C_MASTER_CH_3 3
+#define I2C_MASTER_CH_4 4
+#define I2C_MASTER_CH_5 5
+#define I2C_MASTER_CH_6 6
+#define I2C_MASTER_CH_7 7
+#define I2C_MASTER_CH_8 8
+#define I2C_MASTER_CH_9 9
+#define I2C_MASTER_CH_10 10
+#define I2C_MASTER_CH_11 11
+#define I2C_MASTER_CH_12 12
+#define I2C_MASTER_CH_13 13
+#define I2C_MASTER_CH_14 14
+
+#define I2C_MASTER_CH_TOTAL I2C_MASTER_CH_14
+
+/* SPI_MASTER */
+#define SPI_MASTER_WR_EN 0x1200 /* one bit */
+#define SPI_MASTER_WR_DATA 0x1204 /* 32 bits */
+#define SPI_MASTER_CHK_ID 0x1208 /* one bit */
+#define SPI_MASTER_VERIFY 0x120c /* one bit */
+#define SPI_MASTER_STATUS 0x1210 /* 15 bits */
+#define SPI_MASTER_MODULE_RST 0x1214 /* one bit */
+
+/* FPGA FRONT PANEL PORT MGMT */
+#define SFF_PORT_CTRL_BASE 0x4000
+#define SFF_PORT_STATUS_BASE 0x4004
+#define SFF_PORT_INT_STATUS_BASE 0x4008
+#define SFF_PORT_INT_MASK_BASE 0x400c
+
+#define PORT_XCVR_REGISTER_SIZE 0x1000
+
+/* PORT CTRL REGISTER
+[31:7] RSVD
+[6] RSVD
+[5] MODSEL 5
+[4] RST 4
+[3:1] RSVD
+[0] TXDIS 0
+*/
+#define CTRL_MODSEL 5
+#define CTRL_RST 4
+#define CTRL_TXDIS 0
+
+/* PORT STATUS REGISTER
+[31:6] RSVD
+[5] IRQ 5
+[4] PRESENT 4
+[3] RSVD
+[2] TXFAULT 2
+[1] RXLOS 1
+[0] MODABS 0
+*/
+#define STAT_IRQ 5
+#define STAT_PRESENT 4
+#define STAT_TXFAULT 2
+#define STAT_RXLOS 1
+#define STAT_MODABS 0
+
+/* PORT INTRPT REGISTER
+[31:6] RSVD
+[5] INT_N 5
+[4] PRESENT 4
+[3] RSVD
+[2] RSVD
+[1] RXLOS 1
+[0] MODABS 0
+*/
+#define INTR_INT_N 5
+#define INTR_PRESENT 4
+#define INTR_TXFAULT 2
+#define INTR_RXLOS 1
+#define INTR_MODABS 0
+
+/* PORT INT MASK REGISTER
+[31:6] RSVD
+[5] INT_N 5
+[4] PRESENT 4
+[3] RSVD
+[2] RSVD
+[1] RXLOS_INT 1
+[0] MODABS 0
+*/
+#define MASK_INT_N 5
+#define MASK_PRESENT 4
+#define MASK_TXFAULT 2
+#define MASK_RXLOS 1
+#define MASK_MODABS 0
+
+
+/**
+ * Switchboard CPLD XCVR registers
+ */
+
+/* PORT SEL REGISTER
+[7:5] RSVD
+[4:0] ID
+*/
+#define I2C_XCVR_SEL 0x10
+#define I2C_SEL_ID 0
+
+/* PORT CTRL REGISTER
+[7:5] RSVD
+[4] RST
+[3:1] RSVD
+[0] TXDIS/MODSEL
+*/
+#define I2C_XCVR_CTRL 0x11
+#define I2C_CTRL_RST 4
+#define I2C_CTRL_MODSEL 0
+#define I2C_CTRL_TXDIS 0
+
+/* PORT STATUS REGISTER
+[7:5] RSVD
+[4] PRESENT/ABS
+[3:2] RSVD
+[1] TXFAULT
+[0] RXLOS/INT_N
+*/
+#define I2C_XCVR_STAT 0x12
+#define I2C_STAT_PRESENT 4
+#define I2C_STAT_MODABS 4
+#define I2C_STAT_TXFAULT 1
+#define I2C_STAT_INT_N 0
+#define I2C_STAT_RXLOS 0
+
+/* PORT INTRPT REGISTER
+[7:5] RSVD
+[4] PRESENT/ABS
+[3:2] RSVD
+[1] TXFAULT
+[0] RXLOS/INT_N
+*/
+#define I2C_XCVR_INRT 0x13
+#define I2C_INTR_PRESENT 4
+#define I2C_INTR_MODABS 4
+#define I2C_INTR_TXFAULT 1
+#define I2C_INTR_INT_N 0
+#define I2C_INTR_RXLOS 0
+
+/* PORT INTR MASK REGISTER
+[31:6] RSVD
+[5] INT_N 5
+[4] PRESENT 4
+[3] RSVD
+[2] RSVD
+[1] RXLOS_INT 1
+[0] MODABS 0
+*/
+#define I2C_XCVR_MASK 0x14
+#define I2C_MASK_PRESENT 4
+#define I2C_MASK_MODABS 4
+#define I2C_MASK_TXFAULT 1
+#define I2C_MASK_INT_N 0
+#define I2C_MASK_RXLOS 0
+
+
+/* I2C master clock speed */
+// NOTE: Only I2C clock in normal mode is support here.
+enum {
+ I2C_DIV_100K = 0x71,
+};
+
+/* I2C Master control register */
+enum {
+ I2C_CTRL_IEN = 6,
+ I2C_CTRL_EN
+};
+
+/* I2C Master command register */
+enum {
+ I2C_CMD_IACK = 0,
+ I2C_CMD_ACK = 3,
+ I2C_CMD_WR,
+ I2C_CMD_RD,
+ I2C_CMD_STO,
+ I2C_CMD_STA,
+};
+
+/* I2C Master status register */
+enum {
+ I2C_STAT_IF = 0,
+ I2C_STAT_TIP,
+ I2C_STAT_AL = 5,
+ I2C_STAT_BUSY,
+ I2C_STAT_RxACK,
+};
+
+/**
+ *
+ * The function is i2c algorithm implement to allow master access to
+ * correct endpoint devices trough the PCA9548 switch devices.
+ *
+ * FPGA I2C Master [mutex resource]
+ * |
+ * |
+ * ---------------------------
+ * | PCA9548(s) |
+ * ---1--2--3--4--5--6--7--8--
+ * | | | | | | | |
+ * EEPROM ... EEPROM
+ *
+ */
+
+#define VIRTUAL_I2C_SFP_PORT 0
+#define VIRTUAL_I2C_QSFP_PORT 40
+
+#define SFF_PORT_TOTAL VIRTUAL_I2C_QSFP_PORT + VIRTUAL_I2C_SFP_PORT
+
+#define VIRTUAL_I2C_BUS_OFFSET 10
+#define BB_CPLD_SLAVE_ADDR 0x0d
+#define FAN_CPLD_SLAVE_ADDR 0x0d
+#define CPLD1_SLAVE_ADDR 0x30
+#define CPLD2_SLAVE_ADDR 0x31
+
+static struct class* fpgafwclass = NULL; // < The device-driver class struct pointer
+static struct device* fpgafwdev = NULL; // < The device-driver device struct pointer
+
+#define PCI_VENDOR_ID_TEST 0x1af4
+
+#ifndef PCI_VENDOR_ID_XILINX
+#define PCI_VENDOR_ID_XILINX 0x10EE
+#endif
+
+#define FPGA_PCIE_DEVICE_ID 0x7021
+#define TEST_PCIE_DEVICE_ID 0x1110
+
+
+#ifdef DEBUG_KERN
+#define info(fmt,args...) printk(KERN_INFO "line %3d : "fmt,__LINE__,##args)
+#define check(REG) printk(KERN_INFO "line %3d : %-8s = %2.2X",__LINE__,#REG,ioread8(REG));
+#else
+#define info(fmt,args...)
+#define check(REG)
+#endif
+
+static struct mutex fpga_i2c_master_locks[I2C_MASTER_CH_TOTAL];
+/* Store lasted switch address and channel */
+static uint16_t fpga_i2c_lasted_access_port[I2C_MASTER_CH_TOTAL];
+static int nack_retry[I2C_MASTER_CH_TOTAL];
+static int need_retry[I2C_MASTER_CH_TOTAL];
+
+enum PORT_TYPE {
+ NONE,
+ QSFP,
+ SFP
+};
+
+struct i2c_switch {
+ unsigned char master_bus; // I2C bus number
+ unsigned char switch_addr; // PCA9548 device address, 0xFF if directly connect to a bus.
+ unsigned char channel; // PCA9548 channel number. If the switch_addr is 0xFF, this value is ignored.
+ enum PORT_TYPE port_type; // QSFP/SFP tranceiver port type.
+ char calling_name[20]; // Calling name.
+};
+
+struct i2c_dev_data {
+ int portid;
+ struct i2c_switch pca9548;
+};
+
+/* PREDEFINED I2C SWITCH DEVICE TOPOLOGY */
+static struct i2c_switch fpga_i2c_bus_dev[] = {
+ /* SFP and QSFP front panel I2C */
+ {I2C_MASTER_CH_11, 0x70, 0, QSFP, "QSFP3"}, {I2C_MASTER_CH_11, 0x70, 1, QSFP, "QSFP4"},
+ {I2C_MASTER_CH_11, 0x70, 2, QSFP, "QSFP5"}, {I2C_MASTER_CH_11, 0x70, 3, QSFP, "QSFP6"},
+ {I2C_MASTER_CH_11, 0x70, 4, QSFP, "QSFP7"}, {I2C_MASTER_CH_11, 0x70, 5, QSFP, "QSFP8"},
+ {I2C_MASTER_CH_11, 0x70, 6, QSFP, "QSFP9"}, {I2C_MASTER_CH_11, 0x70, 7, QSFP, "QSFP10"},
+
+ {I2C_MASTER_CH_11, 0x71, 0, QSFP, "QSFP11"}, {I2C_MASTER_CH_11, 0x71, 1, QSFP, "QSFP12"},
+ {I2C_MASTER_CH_11, 0x71, 2, QSFP, "QSFP13"}, {I2C_MASTER_CH_11, 0x71, 3, QSFP, "QSFP14"},
+ {I2C_MASTER_CH_11, 0x71, 4, QSFP, "QSFP15"}, {I2C_MASTER_CH_11, 0x71, 5, QSFP, "QSFP16"},
+ {I2C_MASTER_CH_11, 0x71, 6, QSFP, "QSFP17"}, {I2C_MASTER_CH_11, 0x71, 7, QSFP, "QSFP18"},
+
+ {I2C_MASTER_CH_11, 0x72, 0, QSFP, "QSFP23"}, {I2C_MASTER_CH_11, 0x72, 1, QSFP, "QSFP24"},
+ {I2C_MASTER_CH_11, 0x72, 2, QSFP, "QSFP25"}, {I2C_MASTER_CH_11, 0x72, 3, QSFP, "QSFP26"},
+ {I2C_MASTER_CH_11, 0x72, 4, QSFP, "QSFP27"}, {I2C_MASTER_CH_11, 0x72, 5, QSFP, "QSFP28"},
+ {I2C_MASTER_CH_11, 0x72, 6, QSFP, "QSFP29"}, {I2C_MASTER_CH_11, 0x72, 7, QSFP, "QSFP30"},
+
+ {I2C_MASTER_CH_11, 0x73, 0, QSFP, "QSFP31"}, {I2C_MASTER_CH_11, 0x73, 1, QSFP, "QSFP32"},
+ {I2C_MASTER_CH_11, 0x73, 2, QSFP, "QSFP33"}, {I2C_MASTER_CH_11, 0x73, 3, QSFP, "QSFP34"},
+ {I2C_MASTER_CH_11, 0x73, 4, QSFP, "QSFP35"}, {I2C_MASTER_CH_11, 0x73, 5, QSFP, "QSFP36"},
+ {I2C_MASTER_CH_11, 0x73, 6, QSFP, "QSFP37"}, {I2C_MASTER_CH_11, 0x73, 7, QSFP, "QSFP38"},
+
+ {I2C_MASTER_CH_11, 0x74, 0, QSFP, "QSFP1"}, {I2C_MASTER_CH_11, 0x74, 1, QSFP, "QSFP2"},
+ {I2C_MASTER_CH_11, 0x74, 2, QSFP, "QSFP19"}, {I2C_MASTER_CH_11, 0x74, 3, QSFP, "QSFP20"},
+ {I2C_MASTER_CH_11, 0x74, 4, QSFP, "QSFP21"}, {I2C_MASTER_CH_11, 0x74, 5, QSFP, "QSFP22"},
+ {I2C_MASTER_CH_11, 0x74, 6, QSFP, "QSFP39"}, {I2C_MASTER_CH_11, 0x74, 7, QSFP, "QSFP40"},
+
+ /* Vritual I2C adapters */
+ {I2C_MASTER_CH_1, 0xFF, 0, NONE, "I2C_1"}, // FAN
+ {I2C_MASTER_CH_2, 0xFF, 0, NONE, "I2C_2"},
+ {I2C_MASTER_CH_3, 0xFF, 0, NONE, "I2C_3"},
+ {I2C_MASTER_CH_4, 0xFF, 0, NONE, "I2C_4"},
+ {I2C_MASTER_CH_5, 0xFF, 0, NONE, "I2C_5"}, // BB
+ {I2C_MASTER_CH_6, 0xFF, 0, NONE, "I2C_6"},
+ {I2C_MASTER_CH_7, 0xFF, 0, NONE, "I2C_7"}, // SW
+
+ // NOTE: The bus below are for front panel port debug
+ {I2C_MASTER_CH_11, 0xFF, 0, NONE, "I2C_11"}, // SFF
+
+};
+
+#define VIRTUAL_I2C_PORT_LENGTH ARRAY_SIZE(fpga_i2c_bus_dev)
+#define FAN_I2C_CPLD_INDEX SFF_PORT_TOTAL
+#define BB_I2C_CPLD_INDEX SFF_PORT_TOTAL + 4
+#define SW_I2C_CPLD_INDEX SFF_PORT_TOTAL + 6
+
+struct fpga_device {
+ /* data mmio region */
+ void __iomem *data_base_addr;
+ resource_size_t data_mmio_start;
+ resource_size_t data_mmio_len;
+};
+
+static struct fpga_device fpga_dev = {
+ .data_base_addr = 0,
+ .data_mmio_start = 0,
+ .data_mmio_len = 0,
+};
+
+struct fishbone2_fpga_data {
+ struct device *sff_devices[SFF_PORT_TOTAL];
+ struct i2c_client *sff_i2c_clients[SFF_PORT_TOTAL];
+ struct i2c_adapter *i2c_adapter[VIRTUAL_I2C_PORT_LENGTH];
+ struct mutex fpga_lock; // For FPGA internal lock
+ void __iomem * fpga_read_addr;
+ uint8_t cpld1_read_addr;
+ uint8_t cpld2_read_addr;
+};
+
+struct sff_device_data {
+ int portid;
+ enum PORT_TYPE port_type;
+};
+
+struct fishbone2_fpga_data *fpga_data;
+
+/*
+ * Kernel object for other module drivers.
+ * Other module can use these kobject as a parent.
+ */
+
+static struct kobject *fpga = NULL;
+static struct kobject *cpld1 = NULL;
+static struct kobject *cpld2 = NULL;
+
+/**
+ * Device node in sysfs tree.
+ */
+static struct device *sff_dev = NULL;
+
+/**
+ * Show the value of the register set by 'set_fpga_reg_address'
+ * If the address is not set by 'set_fpga_reg_address' first,
+ * The version register is selected by default.
+ * @param buf register value in hextring
+ * @return number of bytes read, or an error code
+ */
+static ssize_t get_fpga_reg_value(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ // read data from the address
+ uint32_t data;
+ data = ioread32(fpga_data->fpga_read_addr);
+ return sprintf(buf, "0x%8.8x\n", data);
+}
+/**
+ * Store the register address
+ * @param buf address wanted to be read value of
+ * @return number of bytes stored, or an error code
+ */
+static ssize_t set_fpga_reg_address(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ uint32_t addr;
+ char *last;
+
+ addr = (uint32_t)strtoul(buf, &last, 16);
+ if (addr == 0 && buf == last) {
+ return -EINVAL;
+ }
+ fpga_data->fpga_read_addr = fpga_dev.data_base_addr + addr;
+ return count;
+}
+/**
+ * Show value of fpga scratch register
+ * @param buf register value in hexstring
+ * @return number of bytes read, or an error code
+ */
+static ssize_t get_fpga_scratch(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ return sprintf(buf, "0x%8.8x\n", ioread32(fpga_dev.data_base_addr + FPGA_SCRATCH) & 0xffffffff);
+}
+/**
+ * Store value of fpga scratch register
+ * @param buf scratch register value passing from user space
+ * @return number of bytes stored, or an error code
+ */
+static ssize_t set_fpga_scratch(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ uint32_t data;
+ char *last;
+ data = (uint32_t)strtoul(buf, &last, 16);
+ if (data == 0 && buf == last) {
+ return -EINVAL;
+ }
+ iowrite32(data, fpga_dev.data_base_addr + FPGA_SCRATCH);
+ return count;
+}
+/**
+ * Store a value in a specific register address
+ * @param buf the value and address in format '0xhhhh 0xhhhhhhhh'
+ * @return number of bytes sent by user space, or an error code
+ */
+static ssize_t set_fpga_reg_value(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ // register are 4 bytes
+ uint32_t addr;
+ uint32_t value;
+ uint32_t mode = 8;
+ char *tok;
+ char clone[count];
+ char *pclone = clone;
+ char *last;
+
+ strcpy(clone, buf);
+
+ mutex_lock(&fpga_data->fpga_lock);
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ addr = (uint32_t)strtoul(tok, &last, 16);
+ if (addr == 0 && tok == last) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ value = (uint32_t)strtoul(tok, &last, 16);
+ if (value == 0 && tok == last) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ mode = 32;
+ } else {
+ mode = (uint32_t)strtoul(tok, &last, 10);
+ if (mode == 0 && tok == last) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ }
+ if (mode == 32) {
+ iowrite32(value, fpga_dev.data_base_addr + addr);
+ } else if (mode == 8) {
+ iowrite8(value, fpga_dev.data_base_addr + addr);
+ } else {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ mutex_unlock(&fpga_data->fpga_lock);
+ return count;
+}
+
+/* FPGA attributes */
+static DEVICE_ATTR( getreg, 0600, get_fpga_reg_value, set_fpga_reg_address);
+static DEVICE_ATTR( scratch, 0600, get_fpga_scratch, set_fpga_scratch);
+static DEVICE_ATTR( setreg, 0200, NULL , set_fpga_reg_value);
+
+static struct attribute *fpga_attrs[] = {
+ &dev_attr_getreg.attr,
+ &dev_attr_scratch.attr,
+ &dev_attr_setreg.attr,
+ NULL,
+};
+
+static struct attribute_group fpga_attr_grp = {
+ .attrs = fpga_attrs,
+};
+
+/* SW CPLDs attributes */
+static ssize_t cpld1_getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ uint8_t data;
+ fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->cpld1_read_addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+static ssize_t cpld1_getreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ uint8_t addr;
+ char *last;
+ addr = (uint8_t)strtoul(buf, &last, 16);
+ if (addr == 0 && buf == last) {
+ return -EINVAL;
+ }
+ fpga_data->cpld1_read_addr = addr;
+ return size;
+}
+struct device_attribute dev_attr_cpld1_getreg = __ATTR(getreg, 0600, cpld1_getreg_show, cpld1_getreg_store);
+
+static ssize_t cpld1_scratch_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ __u8 data;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+static ssize_t cpld1_scratch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ __u8 data;
+ char *last;
+ int err;
+ data = (uint8_t)strtoul(buf, &last, 16);
+ if (data == 0 && buf == last) {
+ return -EINVAL;
+ }
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return size;
+}
+struct device_attribute dev_attr_cpld1_scratch = __ATTR(scratch, 0600, cpld1_scratch_show, cpld1_scratch_store);
+
+static ssize_t cpld1_setreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+
+ uint8_t addr, value;
+ char *tok;
+ char clone[size];
+ char *pclone = clone;
+ int err;
+ char *last;
+
+ strcpy(clone, buf);
+
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ addr = (uint8_t)strtoul(tok, &last, 16);
+ if (addr == 0 && tok == last) {
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ value = (uint8_t)strtoul(tok, &last, 16);
+ if (value == 0 && tok == last) {
+ return -EINVAL;
+ }
+
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&value);
+ if (err < 0)
+ return err;
+
+ return size;
+}
+struct device_attribute dev_attr_cpld1_setreg = __ATTR(setreg, 0200, NULL, cpld1_setreg_store);
+
+static struct attribute *cpld1_attrs[] = {
+ &dev_attr_cpld1_getreg.attr,
+ &dev_attr_cpld1_scratch.attr,
+ &dev_attr_cpld1_setreg.attr,
+ NULL,
+};
+
+static struct attribute_group cpld1_attr_grp = {
+ .attrs = cpld1_attrs,
+};
+
+static ssize_t cpld2_getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ uint8_t data;
+ fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->cpld2_read_addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+
+static ssize_t cpld2_getreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ uint32_t addr;
+ char *last;
+ addr = (uint8_t)strtoul(buf, &last, 16);
+ if (addr == 0 && buf == last) {
+ return -EINVAL;
+ }
+ fpga_data->cpld2_read_addr = addr;
+ return size;
+}
+struct device_attribute dev_attr_cpld2_getreg = __ATTR(getreg, 0600, cpld2_getreg_show, cpld2_getreg_store);
+
+static ssize_t cpld2_scratch_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ __u8 data;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+
+static ssize_t cpld2_scratch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ __u8 data;
+ char *last;
+ int err;
+
+ data = (uint8_t)strtoul(buf, &last, 16);
+ if (data == 0 && buf == last) {
+ return -EINVAL;
+ }
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return size;
+}
+struct device_attribute dev_attr_cpld2_scratch = __ATTR(scratch, 0600, cpld2_scratch_show, cpld2_scratch_store);
+
+static ssize_t cpld2_setreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ uint8_t addr, value;
+ char *tok;
+ char clone[size];
+ char *pclone = clone;
+ int err;
+ char *last;
+
+ strcpy(clone, buf);
+
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ addr = (uint8_t)strtoul(tok, &last, 16);
+ if (addr == 0 && tok == last) {
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ value = (uint8_t)strtoul(tok, &last, 16);
+ if (value == 0 && tok == last) {
+ return -EINVAL;
+ }
+
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&value);
+ if (err < 0)
+ return err;
+
+ return size;
+}
+struct device_attribute dev_attr_cpld2_setreg = __ATTR(setreg, 0200, NULL, cpld2_setreg_store);
+
+static struct attribute *cpld2_attrs[] = {
+ &dev_attr_cpld2_getreg.attr,
+ &dev_attr_cpld2_scratch.attr,
+ &dev_attr_cpld2_setreg.attr,
+ NULL,
+};
+
+static struct attribute_group cpld2_attr_grp = {
+ .attrs = cpld2_attrs,
+};
+
+/* QSFP/SFP+ attributes */
+static ssize_t qsfp_modirq_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_STAT,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_STAT_INT_N) & 1U);
+}
+DEVICE_ATTR_RO(qsfp_modirq);
+
+static ssize_t qsfp_modprs_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_STAT,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_STAT_MODABS) & 1U);
+}
+DEVICE_ATTR_RO(qsfp_modprs);
+
+static ssize_t sfp_txfault_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_STAT,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_STAT_TXFAULT) & 1U);
+}
+DEVICE_ATTR_RO(sfp_txfault);
+
+static ssize_t sfp_rxlos_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_STAT,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_STAT_RXLOS) & 1U);
+}
+DEVICE_ATTR_RO(sfp_rxlos);
+
+static ssize_t sfp_modabs_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_STAT,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_STAT_MODABS) & 1U);
+}
+DEVICE_ATTR_RO(sfp_modabs);
+
+static ssize_t qsfp_modsel_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_CTRL_MODSEL) & 1U);
+}
+static ssize_t qsfp_modsel_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ ssize_t status;
+ long value;
+ u8 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+
+ status = kstrtol(buf, 0, &value);
+ if (status == 0) {
+ // if value is 0, clear bit.
+ i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_READ);
+ if (!value)
+ data = data & ~( 1U << I2C_CTRL_MODSEL );
+ else
+ data = data | ( 1U << I2C_CTRL_MODSEL );
+ i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_WRITE);
+ status = size;
+ }
+ return status;
+}
+DEVICE_ATTR_RW(qsfp_modsel);
+
+static ssize_t qsfp_reset_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_CTRL_RST) & 1U);
+}
+
+static ssize_t qsfp_reset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ ssize_t status;
+ long value;
+ u8 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+
+ status = kstrtol(buf, 0, &value);
+ if (status == 0) {
+ // if value is 0, reset signal is low
+ i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_READ);
+ if (!value)
+ data = data & ~((u8)0x1 << I2C_CTRL_RST);
+ else
+ data = data | ((u8)0x1 << I2C_CTRL_RST);
+ i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_WRITE);
+ status = size;
+ }
+ return status;
+}
+DEVICE_ATTR_RW(qsfp_reset);
+
+static ssize_t sfp_txdisable_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ int err;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ err = i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_READ);
+ if(err < 0){
+ return err;
+ }
+ return sprintf(buf, "%d\n", (data >> I2C_CTRL_TXDIS) & 1U);
+}
+static ssize_t sfp_txdisable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ ssize_t status;
+ long value;
+ u8 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ status = kstrtol(buf, 0, &value);
+ if (status == 0) {
+ // check if value is 0 clear
+ i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_READ);
+ if (!value)
+ data = data & ~((u8)0x1 << I2C_CTRL_TXDIS);
+ else
+ data = data | ((u8)0x1 << I2C_CTRL_TXDIS);
+ i2c_xcvr_access(I2C_XCVR_CTRL,portid,&data,I2C_SMBUS_WRITE);
+ status = size;
+ }
+ mutex_unlock(&fpga_data->fpga_lock);
+ return status;
+}
+DEVICE_ATTR_RW(sfp_txdisable);
+
+static struct attribute *sff_attrs[] = {
+ &dev_attr_qsfp_modirq.attr,
+ &dev_attr_qsfp_modprs.attr,
+ &dev_attr_qsfp_modsel.attr,
+ &dev_attr_qsfp_reset.attr,
+ &dev_attr_sfp_txfault.attr,
+ &dev_attr_sfp_rxlos.attr,
+ &dev_attr_sfp_modabs.attr,
+ &dev_attr_sfp_txdisable.attr,
+ NULL,
+};
+
+static struct attribute_group sff_attr_grp = {
+ .attrs = sff_attrs,
+};
+
+static const struct attribute_group *sff_attr_grps[] = {
+ &sff_attr_grp,
+ NULL
+};
+
+
+static ssize_t port_led_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // value can be "nomal", "test"
+ __u8 led_mode_1, led_mode_2;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1);
+ if (err < 0)
+ return err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_2);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "%s %s\n",
+ led_mode_1 ? "test" : "normal",
+ led_mode_2 ? "test" : "normal");
+}
+static ssize_t port_led_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ int status;
+ __u8 led_mode_1;
+ if (sysfs_streq(buf, "test")) {
+ led_mode_1 = 0x01;
+ } else if (sysfs_streq(buf, "normal")) {
+ led_mode_1 = 0x00;
+ } else {
+ return -EINVAL;
+ }
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1);
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1);
+ return size;
+}
+DEVICE_ATTR_RW(port_led_mode);
+
+// Only work when port_led_mode set to 1
+static ssize_t port_led_color_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // value can be green/amber/both/alt-blink/OFF
+ __u8 led_color1, led_color2;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color1);
+ if (err < 0)
+ return err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color2);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "%s %s\n",
+ led_color1 == 0x07 ? "off" : led_color1 == 0x06 ? "green" : led_color1 == 0x05 ? "amber" : led_color1 == 0x04 ?
+ "both" : "alt-blink",
+ led_color1 == 0x07 ? "off" : led_color1 == 0x06 ? "green" : led_color1 == 0x05 ? "amber" : led_color1 == 0x04 ?
+ "both" : "alt-blink");
+}
+
+static ssize_t port_led_color_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ int status;
+ __u8 led_color;
+ if (sysfs_streq(buf, "off")) {
+ led_color = 0x07;
+ } else if (sysfs_streq(buf, "green")) {
+ led_color = 0x06;
+ } else if (sysfs_streq(buf, "amber")) {
+ led_color = 0x05;
+ } else if (sysfs_streq(buf, "both")) {
+ led_color = 0x04;
+ } else if (sysfs_streq(buf, "alt-blink")) {
+ led_color = 0x03;
+ } else {
+ status = -EINVAL;
+ return status;
+ }
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x0A, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color);
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x0A, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color);
+ return size;
+}
+DEVICE_ATTR_RW(port_led_color);
+
+static struct attribute *sff_led_test[] = {
+ &dev_attr_port_led_mode.attr,
+ &dev_attr_port_led_color.attr,
+ NULL,
+};
+
+static struct attribute_group sff_led_test_grp = {
+ .attrs = sff_led_test,
+};
+
+static struct device * fishbone2_sff_init(int portid) {
+ struct sff_device_data *new_data;
+ struct device *new_device;
+
+ new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
+ if (!new_data) {
+ printk(KERN_ALERT "Cannot alloc sff device data @port%d", portid);
+ return NULL;
+ }
+ /* The QSFP port ID start from 1 */
+ new_data->portid = portid + 1;
+ new_data->port_type = fpga_i2c_bus_dev[portid].port_type;
+ new_device = device_create_with_groups(fpgafwclass, sff_dev, MKDEV(0, 0), new_data, sff_attr_grps, "%s", fpga_i2c_bus_dev[portid].calling_name);
+ if (IS_ERR(new_device)) {
+ printk(KERN_ALERT "Cannot create sff device @port%d", portid);
+ kfree(new_data);
+ return NULL;
+ }
+ return new_device;
+}
+
+static int i2c_core_init(unsigned int master_bus, unsigned int freq_div,void __iomem *pci_bar){
+
+ unsigned int ctrl;
+ unsigned int REG_FREQ_L;
+ unsigned int REG_FREQ_H;
+ unsigned int REG_CTRL;
+ unsigned int REG_CMD;
+
+ REG_FREQ_L = I2C_MASTER_FREQ_L + (master_bus - 1) * 0x20;
+ REG_FREQ_H = I2C_MASTER_FREQ_H + (master_bus - 1) * 0x20;
+ REG_CTRL = I2C_MASTER_CTRL + (master_bus - 1) * 0x20;
+ REG_CMD = I2C_MASTER_CMD + (master_bus - 1) * 0x20;
+
+ if ( freq_div != I2C_DIV_100K ) {
+ printk(KERN_ERR "FPGA I2C core: Unsupported clock divider: %x\n", freq_div);
+ return -EINVAL;
+ }
+
+ // Makes sure core is disable
+ ctrl = ioread8(pci_bar + REG_CTRL);
+ iowrite8( ctrl & ~(1 << I2C_CTRL_EN | 1 << I2C_CTRL_IEN), pci_bar + REG_CTRL);
+
+ iowrite8( freq_div & 0xFF , pci_bar + REG_FREQ_L);
+ iowrite8( freq_div >> 8, pci_bar + REG_FREQ_H);
+
+ /* Only enable EN bit, we only use polling mode */
+ iowrite8(1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+ iowrite8(1 << I2C_CTRL_EN, pci_bar + REG_CTRL);
+
+ return 0;
+}
+
+static void i2c_core_deinit(unsigned int master_bus,void __iomem *pci_bar){
+
+ unsigned int REG_CTRL;
+ REG_CTRL = I2C_MASTER_CTRL + (master_bus - 1) * 0x20;
+ // Disable core
+ iowrite8( ioread8(pci_bar + REG_CTRL) & ~(1 << I2C_CTRL_EN| 1 << I2C_CTRL_IEN), pci_bar + REG_CTRL);
+}
+
+//FIXME: The hard code seperater below will causing bug!
+//Should pass configuration args into function.
+static int i2c_xcvr_access(u8 register_address, unsigned int portid, u8 *data, char rw){
+
+ u16 dev_addr = 0;
+ int err;
+ /* check for portid valid length */
+ if(portid < 0 || portid > SFF_PORT_TOTAL){
+ return -EINVAL;
+ }
+ if (portid <= 16 ){
+ dev_addr = CPLD1_SLAVE_ADDR;
+ }else{
+ dev_addr = CPLD2_SLAVE_ADDR;
+ portid = portid - 16;
+ }
+ // Select port
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], dev_addr, 0x00, I2C_SMBUS_WRITE,
+ I2C_XCVR_SEL, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&portid);
+ if(err < 0){
+ return err;
+ }
+ // Read/write port xcvr register
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], dev_addr, 0x00, rw,
+ register_address , I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)data);
+ if(err < 0){
+ return err;
+ }
+ return 0;
+}
+
+static int i2c_wait_ack(struct i2c_adapter *a, unsigned long timeout, int writing) {
+ int error = 0;
+ int Status;
+
+ struct i2c_dev_data *new_data = i2c_get_adapdata(a);
+ void __iomem *pci_bar = fpga_dev.data_base_addr;
+
+ unsigned int REG_FREQ_L;
+ unsigned int REG_FREQ_H;
+ unsigned int REG_CMD;
+ unsigned int REG_CTRL;
+ unsigned int REG_STAT;
+ unsigned int REG_DATA;
+
+ unsigned int master_bus = new_data->pca9548.master_bus;
+
+ if (master_bus < I2C_MASTER_CH_1 || master_bus > I2C_MASTER_CH_TOTAL) {
+ error = -EINVAL;
+ return error;
+ }
+
+ REG_FREQ_L = I2C_MASTER_FREQ_L + (master_bus - 1) * 0x20;
+ REG_FREQ_H = I2C_MASTER_FREQ_H + (master_bus - 1) * 0x20;
+ REG_CTRL = I2C_MASTER_CTRL + (master_bus - 1) * 0x20;
+ REG_CMD = I2C_MASTER_CMD + (master_bus - 1) * 0x20;
+ REG_STAT = I2C_MASTER_STATUS + (master_bus - 1) * 0x20;
+ REG_DATA = I2C_MASTER_DATA + (master_bus - 1) * 0x20;
+
+ check(pci_bar + REG_STAT);
+ check(pci_bar + REG_CTRL);
+
+ /*
+ * We wait for the data to be transferred (8bit),
+ * then we start polling on the ACK/NACK bit
+ * udelay((8 * 1000) / 100);
+ */
+ udelay(80);
+ dev_dbg(&a->dev,"Wait for 0x%2.2X\n", 1 << I2C_STAT_TIP);
+
+ timeout = jiffies + msecs_to_jiffies(timeout);
+ while (1) {
+ Status = ioread8(pci_bar + REG_STAT);
+ dev_dbg(&a->dev, "ST:%2.2X\n", Status);
+
+ /* Wait for the TIP bit to be cleared before timeout */
+ if ( (Status & ( 1 << I2C_STAT_TIP )) == 0 ) {
+ dev_dbg(&a->dev, " TIP cleared:0x%2.2X\n", Status);
+ break;
+ }
+
+ if (time_after(jiffies, timeout)) {
+ info("Status %2.2X", Status);
+ info("Error Timeout");
+ error = -ETIMEDOUT;
+ break;
+ }
+
+ cpu_relax();
+ cond_resched();
+ }
+ info("Status %2.2X", Status);
+ info("STA:%x",Status);
+
+ if (error < 0) {
+ dev_dbg(&a->dev, "%s TIMEOUT bit 0x%x not clear in specific time\n",
+ __func__, (1 << I2C_STAT_TIP));
+ return error;
+ }
+
+ /** There is only one master in each bus. If this error happen something is
+ * not normal in i2c transfer refer to:
+ * https://www.i2c-bus.org/i2c-primer/analysing-obscure-problems/master-reports-arbitration-lost
+ */
+ // Arbitration lost
+ if (Status & (1 << I2C_STAT_AL)) {
+ info("Error arbitration lost");
+ nack_retry[master_bus - 1] = 1;
+ return -EBUSY;
+ }
+
+ // Ack not received
+ if (Status & (1 << I2C_STAT_RxACK)) {
+ info( "SL No ACK");
+ if (writing) {
+ info("Error No ACK");
+ nack_retry[master_bus - 1] = 1;
+ return -EIO;
+ }
+ } else {
+ info( "SL ACK");
+ }
+
+ return error;
+}
+
+static int i2c_wait_stop(struct i2c_adapter *a, unsigned long timeout, int writing) {
+ int error = 0;
+ int Status;
+
+ struct i2c_dev_data *new_data = i2c_get_adapdata(a);
+ void __iomem *pci_bar = fpga_dev.data_base_addr;
+
+ unsigned int REG_FREQ_L;
+ unsigned int REG_FREQ_H;
+ unsigned int REG_CMD;
+ unsigned int REG_CTRL;
+ unsigned int REG_STAT;
+ unsigned int REG_DATA;
+
+ unsigned int master_bus = new_data->pca9548.master_bus;
+
+ if (master_bus < I2C_MASTER_CH_1 || master_bus > I2C_MASTER_CH_TOTAL) {
+ error = -EINVAL;
+ return error;
+ }
+
+ REG_FREQ_L = I2C_MASTER_FREQ_L + (master_bus - 1) * 0x20;
+ REG_FREQ_H = I2C_MASTER_FREQ_H + (master_bus - 1) * 0x20;
+ REG_CTRL = I2C_MASTER_CTRL + (master_bus - 1) * 0x20;
+ REG_CMD = I2C_MASTER_CMD + (master_bus - 1) * 0x20;
+ REG_STAT = I2C_MASTER_STATUS + (master_bus - 1) * 0x20;
+ REG_DATA = I2C_MASTER_DATA + (master_bus - 1) * 0x20;
+
+ check(pci_bar + REG_STAT);
+ check(pci_bar + REG_CTRL);
+
+ dev_dbg(&a->dev,"Wait for 0x%2.2X\n", 1 << I2C_STAT_BUSY);
+ timeout = jiffies + msecs_to_jiffies(timeout);
+ while (1) {
+ Status = ioread8(pci_bar + REG_STAT);
+ dev_dbg(&a->dev, "ST:%2.2X\n", Status);
+ if (time_after(jiffies, timeout)) {
+ info("Status %2.2X", Status);
+ info("Error Timeout");
+ error = -ETIMEDOUT;
+ break;
+ }
+
+ /* Wait for the BUSY bit to be cleared before timeout */
+ if ( (Status & ( 1 << I2C_STAT_BUSY )) == 0 ) {
+ dev_dbg(&a->dev, " BUSY cleared:0x%2.2X\n", Status);
+ break;
+ }
+
+ cpu_relax();
+ cond_resched();
+ }
+ info("Status %2.2X", Status);
+ info("STA:%x",Status);
+
+ if (error < 0) {
+ dev_dbg(&a->dev, "%s TIMEOUT bit 0x%x not clear in specific time\n",
+ __func__, (1 << I2C_STAT_BUSY));
+ return error;
+ }
+ return 0;
+}
+
+/* SMBUS Xfer for opencore I2C with polling */
+// TODO: Change smbus_xfer to master_xfer - This will support i2c and all smbus emu functions.
+static int smbus_access(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char rw, u8 cmd,
+ int size, union i2c_smbus_data *data)
+{
+ int error = 0;
+ int cnt = 0;
+ int bid = 0;
+ struct i2c_dev_data *dev_data;
+ void __iomem *pci_bar;
+ unsigned int portid, master_bus;
+ int error_stop = 0;
+
+ unsigned int REG_FREQ_L;
+ unsigned int REG_FREQ_H;
+ unsigned int REG_CMD;
+ unsigned int REG_CTRL;
+ unsigned int REG_STAT;
+ unsigned int REG_DATA;
+
+ REG_FREQ_L = 0;
+ REG_FREQ_H = 0;
+ REG_CTRL = 0;
+ REG_CMD = 0;
+ REG_STAT = 0;
+ REG_DATA = 0;
+
+ /* Write the command register */
+ dev_data = i2c_get_adapdata(adapter);
+ portid = dev_data->portid;
+ pci_bar = fpga_dev.data_base_addr;
+
+#ifdef DEBUG_KERN
+ printk(KERN_INFO "portid %2d|@ 0x%2.2X|f 0x%4.4X|(%d)%-5s| (%d)%-10s|CMD %2.2X "
+ , portid, addr, flags, rw, rw == 1 ? "READ " : "WRITE"
+ , size, size == 0 ? "QUICK" :
+ size == 1 ? "BYTE" :
+ size == 2 ? "BYTE_DATA" :
+ size == 3 ? "WORD_DATA" :
+ size == 4 ? "PROC_CALL" :
+ size == 5 ? "BLOCK_DATA" :
+ size == 8 ? "I2C_BLOCK_DATA" : "ERROR"
+ , cmd);
+#endif
+
+ master_bus = dev_data->pca9548.master_bus;
+ error = i2c_core_init(master_bus, I2C_DIV_100K, fpga_dev.data_base_addr);
+
+ /* Map the size to what the chip understands */
+ switch (size) {
+ case I2C_SMBUS_QUICK:
+ case I2C_SMBUS_BYTE:
+ case I2C_SMBUS_BYTE_DATA:
+ case I2C_SMBUS_WORD_DATA:
+ case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ break;
+ default:
+ printk(KERN_INFO "Unsupported transaction %d\n", size);
+ error = -EOPNOTSUPP;
+ goto Done;
+ }
+
+ master_bus = dev_data->pca9548.master_bus;
+
+ if (master_bus < I2C_MASTER_CH_1 || master_bus > I2C_MASTER_CH_TOTAL) {
+ error = -EINVAL;
+ goto Done;
+ }
+
+ REG_FREQ_L = I2C_MASTER_FREQ_L + (master_bus - 1) * 0x20;
+ REG_FREQ_H = I2C_MASTER_FREQ_H + (master_bus - 1) * 0x20;
+ REG_CTRL = I2C_MASTER_CTRL + (master_bus - 1) * 0x20;
+ REG_CMD = I2C_MASTER_CMD + (master_bus - 1) * 0x20;
+ REG_STAT = I2C_MASTER_STATUS + (master_bus - 1) * 0x20;
+ REG_DATA = I2C_MASTER_DATA + (master_bus - 1) * 0x20;
+
+ ////[S][ADDR/R]
+ if (rw == I2C_SMBUS_READ &&
+ (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE)) {
+ // sent device address with Read mode
+ iowrite8( (addr << 1) | 0x01, pci_bar + REG_DATA);
+ } else {
+ // sent device address with Write mode
+ iowrite8( (addr << 1) & 0xFE, pci_bar + REG_DATA);
+ }
+ iowrite8( 1 << I2C_CMD_STA | 1 << I2C_CMD_WR | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+
+ info( "MS Start");
+
+ //// Wait {A}
+ // + IACK
+ error = i2c_wait_ack(adapter, 30, 1);
+ if (error < 0) {
+ info( "get error %d", error);
+ dev_dbg(&adapter->dev,"START Error: %d\n", error);
+ goto Done;
+ }
+
+ //// [CMD]{A}
+ if (size == I2C_SMBUS_BYTE_DATA ||
+ size == I2C_SMBUS_WORD_DATA ||
+ size == I2C_SMBUS_BLOCK_DATA ||
+ size == I2C_SMBUS_I2C_BLOCK_DATA ||
+ (size == I2C_SMBUS_BYTE && rw == I2C_SMBUS_WRITE)) {
+
+ // sent command code to data register
+ iowrite8(cmd, pci_bar + REG_DATA);
+ // Start the transfer
+ iowrite8(1 << I2C_CMD_WR | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+ info( "MS Send CMD 0x%2.2X", cmd);
+
+ // Wait {A}
+ // IACK
+ error = i2c_wait_ack(adapter, 30, 1);
+ if (error < 0) {
+ info( "get error %d", error);
+ dev_dbg(&adapter->dev,"CMD Error: %d\n", error);
+ goto Done;
+ }
+ }
+
+ switch (size) {
+ case I2C_SMBUS_BYTE_DATA:
+ cnt = 1; break;
+ case I2C_SMBUS_WORD_DATA:
+ cnt = 2; break;
+ case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ /* in block data mode keep number of byte in block[0] */
+ cnt = data->block[0];
+ break;
+ default:
+ cnt = 0; break;
+ }
+
+ // [CNT] used only block data write
+ if (size == I2C_SMBUS_BLOCK_DATA && rw == I2C_SMBUS_WRITE) {
+
+ iowrite8(cnt, pci_bar + REG_DATA);
+ //Start the transfer
+ iowrite8(1 << I2C_CMD_WR | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+ info( "MS Send CNT 0x%2.2X", cnt);
+
+ // Wait {A}
+ // IACK
+ error = i2c_wait_ack(adapter, 30, 1);
+ if (error < 0) {
+ info( "get error %d", error);
+ dev_dbg(&adapter->dev,"CNT Error: %d\n", error);
+ goto Done;
+ }
+ }
+
+ // [DATA]{A}
+ if ( rw == I2C_SMBUS_WRITE && (
+ size == I2C_SMBUS_BYTE ||
+ size == I2C_SMBUS_BYTE_DATA ||
+ size == I2C_SMBUS_WORD_DATA ||
+ size == I2C_SMBUS_BLOCK_DATA ||
+ size == I2C_SMBUS_I2C_BLOCK_DATA
+ )) {
+ int bid = 0;
+ info( "MS prepare to sent [%d bytes]", cnt);
+ if (size == I2C_SMBUS_BLOCK_DATA || size == I2C_SMBUS_I2C_BLOCK_DATA) {
+ bid = 1; // block[0] is cnt;
+ cnt += 1; // offset from block[0]
+ }
+ for (; bid < cnt; bid++) {
+ info("STA:%x", ioread8(pci_bar + REG_STAT) );
+ info( " Data > %2.2X", data->block[bid]);
+ iowrite8(data->block[bid], pci_bar + REG_DATA);
+ iowrite8(1 << I2C_CMD_WR | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+
+ // Wait {A}
+ // IACK
+ error = i2c_wait_ack(adapter, 30, 1);
+ if (error < 0) {
+ dev_dbg(&adapter->dev,"Send DATA Error: %d\n", error);
+ goto Done;
+ }
+ }
+ }
+
+ //REPEATE START
+ if ( rw == I2C_SMBUS_READ && (
+ size == I2C_SMBUS_BYTE_DATA ||
+ size == I2C_SMBUS_WORD_DATA ||
+ size == I2C_SMBUS_BLOCK_DATA ||
+ size == I2C_SMBUS_I2C_BLOCK_DATA
+ )) {
+ info( "MS Repeated Start");
+
+ // sent Address with Read mode
+ iowrite8( addr << 1 | 0x1 , pci_bar + REG_DATA);
+ // SET START | WRITE
+ iowrite8( 1 << I2C_CMD_STA | 1 << I2C_CMD_WR | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+
+ // Wait {A}
+ error = i2c_wait_ack(adapter, 30, 1);
+ if (error < 0) {
+ dev_dbg(&adapter->dev,"Repeat START Error: %d\n", error);
+ goto Done;
+ }
+
+ }
+
+ if ( rw == I2C_SMBUS_READ && (
+ size == I2C_SMBUS_BYTE ||
+ size == I2C_SMBUS_BYTE_DATA ||
+ size == I2C_SMBUS_WORD_DATA ||
+ size == I2C_SMBUS_BLOCK_DATA ||
+ size == I2C_SMBUS_I2C_BLOCK_DATA
+ )) {
+
+ switch (size) {
+ case I2C_SMBUS_BYTE:
+ case I2C_SMBUS_BYTE_DATA:
+ cnt = 1; break;
+ case I2C_SMBUS_WORD_DATA:
+ cnt = 2; break;
+ case I2C_SMBUS_BLOCK_DATA:
+ /* will be changed after recived first data */
+ cnt = 3; break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ cnt = data->block[0]; break;
+ default:
+ cnt = 0; break;
+ }
+
+ info( "MS Receive");
+
+ for (bid = 0; bid < cnt; bid++) {
+
+ // Start receive FSM
+ if (bid == cnt - 1) {
+ info( "READ NACK");
+ iowrite8(1 << I2C_CMD_RD | 1 << I2C_CMD_ACK | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+ }else{
+
+ iowrite8(1 << I2C_CMD_RD, pci_bar + REG_CMD);
+ }
+
+ // Wait {A}
+ error = i2c_wait_ack(adapter, 30, 0);
+ if(nack_retry[master_bus - 1] == 1)
+ {
+ need_retry[master_bus - 1] = 1;
+ }
+ if (error < 0) {
+ dev_dbg(&adapter->dev,"Receive DATA Error: %d\n", error);
+ goto Done;
+ }
+ if(size == I2C_SMBUS_I2C_BLOCK_DATA){
+ /* block[0] is read length */
+ data->block[bid+1] = ioread8(pci_bar + REG_DATA);
+ info( "DATA IN [%d] %2.2X", bid+1, data->block[bid+1]);
+ }else {
+ data->block[bid] = ioread8(pci_bar + REG_DATA);
+ info( "DATA IN [%d] %2.2X", bid, data->block[bid]);
+ }
+ if (size == I2C_SMBUS_BLOCK_DATA && bid == 0) {
+ cnt = data->block[0] + 1;
+ }
+ }
+ }
+
+Done:
+ info( "MS STOP");
+ // SET STOP
+ iowrite8( 1 << I2C_CMD_STO | 1 << I2C_CMD_IACK, pci_bar + REG_CMD);
+ // Wait for the STO to finish.
+ error_stop = i2c_wait_stop(adapter, 30, 0);
+ if (error_stop < 0) {
+ dev_dbg(&adapter->dev,"STOP Error: %d\n", error_stop);
+ }
+ check(pci_bar + REG_CTRL);
+ check(pci_bar + REG_STAT);
+#ifdef DEBUG_KERN
+ printk(KERN_INFO "END --- Error code %d", error);
+#endif
+
+ return error;
+}
+
+/**
+ * Wrapper of smbus_access access with PCA9548 I2C switch management.
+ * This function set PCA9548 switches to the proper slave channel.
+ * Only one channel among switches chip is selected during communication time.
+ *
+ * Note: If the bus does not have any PCA9548 on it, the switch_addr must be
+ * set to 0xFF, it will use normal smbus_access function.
+ */
+static int fpga_i2c_access(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char rw, u8 cmd,
+ int size, union i2c_smbus_data *data)
+{
+ int error, retval = 0;
+ struct i2c_dev_data *dev_data;
+ unsigned char master_bus;
+ unsigned char switch_addr;
+ unsigned char channel;
+ unsigned char *calling_name;
+ uint16_t prev_port = 0;
+ unsigned char prev_switch;
+ unsigned char prev_ch;
+ uint8_t read_channel;
+ int retry = 0;
+
+ dev_data = i2c_get_adapdata(adapter);
+ master_bus = dev_data->pca9548.master_bus;
+ switch_addr = dev_data->pca9548.switch_addr;
+ channel = dev_data->pca9548.channel;
+ calling_name = dev_data->pca9548.calling_name;
+
+ // Acquire the master resource.
+ mutex_lock(&fpga_i2c_master_locks[master_bus - 1]);
+ prev_port = fpga_i2c_lasted_access_port[master_bus - 1];
+ prev_switch = (unsigned char)(prev_port >> 8) & 0xFF;
+ prev_ch = (unsigned char)(prev_port & 0xFF);
+
+ if (switch_addr != 0xFF) {
+
+ // Check lasted access switch address on a master
+ // Only select new channel of a switch if they are difference from last channel of a switch
+ if ( prev_switch != switch_addr && prev_switch != 0 ) {
+ // reset prev_port PCA9548 chip
+ retry = 3;
+ while(retry--){
+ error = smbus_access(adapter, (u16)(prev_switch), flags, I2C_SMBUS_WRITE, 0x00, I2C_SMBUS_BYTE, NULL);
+ if(error >= 0){
+ break;
+ }else{
+ dev_dbg(&adapter->dev,"Failed to deselect ch %d of 0x%x, CODE %d\n", prev_ch, prev_switch, error);
+ }
+
+ }
+ if(retry < 0)
+ goto release_unlock;
+ // set PCA9548 to current channel
+ retry = 3;
+ while(retry--){
+ error = smbus_access(adapter, switch_addr, flags, I2C_SMBUS_WRITE, 1 << channel, I2C_SMBUS_BYTE, NULL);
+ if(error >= 0){
+ break;
+ }else{
+ dev_dbg(&adapter->dev,"Failed to select ch %d of 0x%x, CODE %d\n", prev_ch, prev_switch, error);
+ }
+
+ }
+ if(retry < 0){
+ goto release_unlock;
+ }
+ // update lasted port
+ fpga_i2c_lasted_access_port[master_bus - 1] = switch_addr << 8 | channel;
+
+ } else {
+ // check if channel is also changes
+ if ( prev_ch != channel || prev_switch == 0 ) {
+ // set new PCA9548 at switch_addr to current
+ retry = 3;
+ while(retry--){
+ error = smbus_access(adapter, switch_addr, flags, I2C_SMBUS_WRITE, 1 << channel, I2C_SMBUS_BYTE, NULL);
+ if(error >= 0){
+ break;
+ }else{
+ dev_dbg(&adapter->dev,"Failed to select ch %d of 0x%x, CODE %d\n", prev_ch, prev_switch, error);
+ }
+ }
+ if(retry < 0){
+ goto release_unlock;
+ }
+ // update lasted port
+ fpga_i2c_lasted_access_port[master_bus - 1] = switch_addr << 8 | channel;
+ }
+ }
+ }
+
+ // Do SMBus communication
+ nack_retry[master_bus - 1] = 0;
+ need_retry[master_bus - 1] = 0;
+ error = smbus_access(adapter, addr, flags, rw, cmd, size, data);
+ if((nack_retry[master_bus - 1]==1)&&(need_retry[master_bus - 1]==1))
+ retry = 2000;
+ else
+ retry = 5;
+ // If the first access failed, do retry.
+ while((nack_retry[master_bus - 1]==1)&&retry)
+ {
+ retry--;
+ nack_retry[master_bus - 1] = 0;
+ dev_dbg(&adapter->dev,"error = %d\n",error);
+ error = smbus_access(adapter, addr, flags, rw, cmd, size, data);
+ dev_dbg(&adapter->dev,"nack retry = %d\n",retry);
+ }
+ nack_retry[master_bus - 1] = 0;
+ need_retry[master_bus - 1] = 0;
+
+ retval = error;
+
+ if(error < 0){
+ dev_dbg( &adapter->dev,"smbus_xfer failed (%d) @ 0x%2.2X|f 0x%4.4X|(%d)%-5s| (%d)%-10s|CMD %2.2X "
+ , error, addr, flags, rw, rw == 1 ? "READ " : "WRITE"
+ , size, size == 0 ? "QUICK" :
+ size == 1 ? "BYTE" :
+ size == 2 ? "BYTE_DATA" :
+ size == 3 ? "WORD_DATA" :
+ size == 4 ? "PROC_CALL" :
+ size == 5 ? "BLOCK_DATA" :
+ size == 8 ? "I2C_BLOCK_DATA" : "ERROR"
+ , cmd);
+ }else{
+ goto release_unlock;
+ }
+
+ /** For the bus with PCA9548, try to read PCA9548 one more time.
+ * For the bus w/o PCA9548 just check the return from last time.
+ */
+ if (switch_addr != 0xFF) {
+ error = smbus_access(adapter, switch_addr, flags, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE, (union i2c_smbus_data*)&read_channel);
+ dev_dbg(&adapter->dev,"Try access I2C switch device at %2.2x\n", switch_addr);
+ if(error < 0){
+ dev_dbg(&adapter->dev,"Unbale to access switch device.\n");
+ }else{
+ dev_dbg(&adapter->dev,"Read success, register val %2.2x\n", read_channel);
+ }
+ }
+
+ // If retry was used up(retry = 0) and the last transfer result is -EBUSY
+ if(retry <= 0 && error == -EBUSY ){
+ retval = error;
+ // raise device error message
+ dev_err(&adapter->dev, "I2C bus hangup detected on %s port.\n", calling_name);
+
+ /**
+ * Fishbone2: Device specific I2C reset topology
+ */
+ if( master_bus == I2C_MASTER_CH_11 ){
+ dev_notice(&adapter->dev, "Trying bus recovery...\n");
+ dev_notice(&adapter->dev, "Reset I2C switch device.\n");
+
+ // reset PCA9548 on the current BUS.
+ iowrite8( ioread8(fpga_dev.data_base_addr + 0x0108) & 0xF0, fpga_dev.data_base_addr + 0x0108);
+ udelay(1);
+ iowrite8( ioread8(fpga_dev.data_base_addr + 0x0108) | 0x0F, fpga_dev.data_base_addr + 0x0108);
+ // clear the last access port
+ fpga_i2c_lasted_access_port[master_bus - 1] = 0;
+ }else{
+ dev_crit(&adapter->dev, "I2C bus unrecoverable.\n");
+ }
+ }
+
+
+release_unlock:
+ mutex_unlock(&fpga_i2c_master_locks[master_bus - 1]);
+ dev_dbg(&adapter->dev,"switch ch %d of 0x%x -> ch %d of 0x%x\n", prev_ch, prev_switch, channel, switch_addr);
+ return retval;
+}
+
+/**
+ * A callback function show available smbus functions.
+ */
+static u32 fpga_i2c_func(struct i2c_adapter *a)
+{
+ return I2C_FUNC_SMBUS_QUICK |
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA|
+ I2C_FUNC_SMBUS_I2C_BLOCK;
+}
+
+static const struct i2c_algorithm fishbone2_i2c_algorithm = {
+ .smbus_xfer = fpga_i2c_access,
+ .functionality = fpga_i2c_func,
+};
+
+/**
+ * Create virtual I2C bus adapter for switch devices
+ * @param pdev platform device pointer
+ * @param portid virtual i2c port id for switch device mapping
+ * @param bus_number_offset bus offset for virtual i2c adapter in system
+ * @return i2c adapter.
+ *
+ * When bus_number_offset is -1, created adapter with dynamic bus number.
+ * Otherwise create adapter at i2c bus = bus_number_offset + portid.
+ */
+static struct i2c_adapter * fishbone2_i2c_init(struct platform_device *pdev, int portid, int bus_number_offset)
+{
+ int error;
+
+ struct i2c_adapter *new_adapter;
+ struct i2c_dev_data *new_data;
+
+ new_adapter = kzalloc(sizeof(*new_adapter), GFP_KERNEL);
+ if (!new_adapter) {
+ printk(KERN_ALERT "Cannot alloc i2c adapter for %s", fpga_i2c_bus_dev[portid].calling_name);
+ return NULL;
+ }
+
+ new_adapter->owner = THIS_MODULE;
+ new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ new_adapter->algo = &fishbone2_i2c_algorithm;
+ /* If the bus offset is -1, use dynamic bus number */
+ if (bus_number_offset == -1) {
+ new_adapter->nr = -1;
+ } else {
+ new_adapter->nr = bus_number_offset + portid;
+ }
+
+ new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
+ if (!new_data) {
+ printk(KERN_ALERT "Cannot alloc i2c data for %s", fpga_i2c_bus_dev[portid].calling_name);
+ kzfree(new_adapter);
+ return NULL;
+ }
+
+ new_data->portid = portid;
+ new_data->pca9548.master_bus = fpga_i2c_bus_dev[portid].master_bus;
+ new_data->pca9548.switch_addr = fpga_i2c_bus_dev[portid].switch_addr;
+ new_data->pca9548.channel = fpga_i2c_bus_dev[portid].channel;
+ strcpy(new_data->pca9548.calling_name, fpga_i2c_bus_dev[portid].calling_name);
+
+ snprintf(new_adapter->name, sizeof(new_adapter->name),
+ "SMBus I2C Adapter PortID: %s", new_data->pca9548.calling_name);
+
+ i2c_set_adapdata(new_adapter, new_data);
+ error = i2c_add_numbered_adapter(new_adapter);
+ if (error < 0) {
+ printk(KERN_ALERT "Cannot add i2c adapter %s", new_data->pca9548.calling_name);
+ kzfree(new_adapter);
+ kzfree(new_data);
+ return NULL;
+ }
+
+ return new_adapter;
+};
+
+// I/O resource need.
+static struct resource fishbone2_resources[] = {
+ {
+ .start = 0x10000000,
+ .end = 0x10001000,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static void fishbone2_dev_release( struct device * dev)
+{
+ return;
+}
+
+static struct platform_device fishbone2_dev = {
+ .name = DRIVER_NAME,
+ .id = -1,
+ .num_resources = ARRAY_SIZE(fishbone2_resources),
+ .resource = fishbone2_resources,
+ .dev = {
+ .release = fishbone2_dev_release,
+ }
+};
+
+/**
+ * Board info for QSFP/SFP+ eeprom.
+ * Note: Using OOM optoe as transceiver eeprom driver.
+ * https://www.opencompute.org/wiki/Networking/SpecsAndDesigns#Open_Optical_Monitoring
+ */
+static struct i2c_board_info sff8436_eeprom_info[] = {
+ { I2C_BOARD_INFO("optoe1", 0x50) }, //For QSFP w/ sff8436
+ { I2C_BOARD_INFO("optoe2", 0x50) }, //For SFP+ w/ sff8472
+};
+
+static int fishbone2_drv_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int ret = 0;
+ int portid_count;
+ uint8_t cpld1_version, cpld2_version;
+ uint16_t prev_i2c_switch = 0;
+ struct sff_device_data *sff_data;
+
+ /* The device class need to be instantiated before this function called */
+ BUG_ON(fpgafwclass == NULL);
+
+ fpga_data = devm_kzalloc(&pdev->dev, sizeof(struct fishbone2_fpga_data),
+ GFP_KERNEL);
+
+ if (!fpga_data)
+ return -ENOMEM;
+
+ // Set default read address to VERSION
+ fpga_data->fpga_read_addr = fpga_dev.data_base_addr + FPGA_VERSION;
+ fpga_data->cpld1_read_addr = 0x00;
+ fpga_data->cpld2_read_addr = 0x00;
+
+ mutex_init(&fpga_data->fpga_lock);
+ for (ret = I2C_MASTER_CH_1 ; ret <= I2C_MASTER_CH_TOTAL; ret++) {
+ mutex_init(&fpga_i2c_master_locks[ret - 1]);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (unlikely(!res)) {
+ printk(KERN_ERR "Specified Resource Not Available...\n");
+ kzfree(fpga_data);
+ return -1;
+ }
+
+ fpga = kobject_create_and_add("FPGA", &pdev->dev.kobj);
+ if (!fpga) {
+ kzfree(fpga_data);
+ return -ENOMEM;
+ }
+
+ ret = sysfs_create_group(fpga, &fpga_attr_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create FPGA sysfs attributes\n");
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ cpld1 = kobject_create_and_add("CPLD1", &pdev->dev.kobj);
+ if (!cpld1) {
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return -ENOMEM;
+ }
+ ret = sysfs_create_group(cpld1, &cpld1_attr_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create CPLD1 sysfs attributes\n");
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ cpld2 = kobject_create_and_add("CPLD2", &pdev->dev.kobj);
+ if (!cpld2) {
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return -ENOMEM;
+ }
+ ret = sysfs_create_group(cpld2, &cpld2_attr_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create CPLD2 sysfs attributes\n");
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ sff_dev = device_create(fpgafwclass, NULL, MKDEV(0, 0), NULL, "sff_device");
+ if (IS_ERR(sff_dev)) {
+ printk(KERN_ERR "Failed to create sff device\n");
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return PTR_ERR(sff_dev);
+ }
+
+ ret = sysfs_create_group(&sff_dev->kobj, &sff_led_test_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create SFF attributes\n");
+ device_destroy(fpgafwclass, MKDEV(0, 0));
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ ret = sysfs_create_link(&pdev->dev.kobj, &sff_dev->kobj, "SFF");
+ if (ret != 0) {
+ sysfs_remove_group(&sff_dev->kobj, &sff_led_test_grp);
+ device_destroy(fpgafwclass, MKDEV(0, 0));
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ for (portid_count = I2C_MASTER_CH_1; portid_count <= I2C_MASTER_CH_TOTAL; portid_count++){
+ if(!allow_unsafe_i2c_access){
+ if( portid_count < I2C_MASTER_CH_7 ||
+ portid_count == I2C_MASTER_CH_9 || portid_count == I2C_MASTER_CH_10 )
+ continue;
+ }
+ ret = i2c_core_init(portid_count, I2C_DIV_100K, fpga_dev.data_base_addr);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Unable to init I2C core %d\n", portid_count);
+ sysfs_remove_group(&sff_dev->kobj, &sff_led_test_grp);
+ device_destroy(fpgafwclass, MKDEV(0, 0));
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+ }
+
+ for (portid_count = 0 ; portid_count < VIRTUAL_I2C_PORT_LENGTH ; portid_count++) {
+ if(!allow_unsafe_i2c_access){
+ if( portid_count >= FAN_I2C_CPLD_INDEX && portid_count < SW_I2C_CPLD_INDEX ){
+ fpga_data->i2c_adapter[portid_count] = NULL;
+ continue;
+ }
+ }
+ fpga_data->i2c_adapter[portid_count] = fishbone2_i2c_init(pdev, portid_count, VIRTUAL_I2C_BUS_OFFSET);
+ }
+
+ /* Init SFF devices */
+ for (portid_count = 0; portid_count < SFF_PORT_TOTAL; portid_count++) {
+ struct i2c_adapter *i2c_adap = fpga_data->i2c_adapter[portid_count];
+ if (i2c_adap) {
+ fpga_data->sff_devices[portid_count] = fishbone2_sff_init(portid_count);
+ sff_data = dev_get_drvdata(fpga_data->sff_devices[portid_count]);
+ BUG_ON(sff_data == NULL);
+ if ( sff_data->port_type == QSFP ) {
+ fpga_data->sff_i2c_clients[portid_count] = i2c_new_device(i2c_adap, &sff8436_eeprom_info[0]);
+ } else {
+ fpga_data->sff_i2c_clients[portid_count] = i2c_new_device(i2c_adap, &sff8436_eeprom_info[1]);
+ }
+ sff_data = NULL;
+ sysfs_create_link(&fpga_data->sff_devices[portid_count]->kobj,
+ &fpga_data->sff_i2c_clients[portid_count]->dev.kobj,
+ "i2c");
+ }
+ }
+
+ printk(KERN_INFO "Virtual I2C buses created\n");
+
+#ifdef TEST_MODE
+ return 0;
+#endif
+ fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&cpld1_version);
+ fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&cpld2_version);
+
+ printk(KERN_INFO "Switch CPLD1 Version: %2.2x\n", cpld1_version);
+ printk(KERN_INFO "Switch CPLD2 Version: %2.2x\n", cpld2_version);
+
+
+ /* Init I2C buses that has PCA9548 switch device. */
+ for (portid_count = 0; portid_count < VIRTUAL_I2C_PORT_LENGTH; portid_count++) {
+
+ if(!allow_unsafe_i2c_access){
+ if( portid_count >= FAN_I2C_CPLD_INDEX && portid_count < SW_I2C_CPLD_INDEX ){
+ continue;
+ }
+ }
+
+ struct i2c_dev_data *dev_data;
+ unsigned char master_bus;
+ unsigned char switch_addr;
+
+ dev_data = i2c_get_adapdata(fpga_data->i2c_adapter[portid_count]);
+ master_bus = dev_data->pca9548.master_bus;
+ switch_addr = dev_data->pca9548.switch_addr;
+
+ if (switch_addr != 0xFF) {
+
+ if (prev_i2c_switch != ( (master_bus << 8) | switch_addr) ) {
+ // Found the bus with PCA9548, trying to clear all switch in it.
+ smbus_access(fpga_data->i2c_adapter[portid_count], switch_addr, 0x00, I2C_SMBUS_WRITE, 0x00, I2C_SMBUS_BYTE, NULL);
+ prev_i2c_switch = ( master_bus << 8 ) | switch_addr;
+ }
+ }
+ }
+ return 0;
+}
+
+static int fishbone2_drv_remove(struct platform_device *pdev)
+{
+ int portid_count;
+ struct sff_device_data *rem_data;
+ struct i2c_dev_data *adap_data;
+
+ for (portid_count = 0; portid_count < SFF_PORT_TOTAL; portid_count++) {
+ sysfs_remove_link(&fpga_data->sff_devices[portid_count]->kobj, "i2c");
+ i2c_unregister_device(fpga_data->sff_i2c_clients[portid_count]);
+ }
+
+ for (portid_count = 0 ; portid_count < VIRTUAL_I2C_PORT_LENGTH ; portid_count++) {
+ if (fpga_data->i2c_adapter[portid_count] != NULL) {
+ info(KERN_INFO "<%x>", fpga_data->i2c_adapter[portid_count]);
+ adap_data = i2c_get_adapdata(fpga_data->i2c_adapter[portid_count]);
+ i2c_del_adapter(fpga_data->i2c_adapter[portid_count]);
+ }
+ }
+
+ for (portid_count = I2C_MASTER_CH_1; portid_count <= I2C_MASTER_CH_TOTAL; portid_count++){
+ if(!allow_unsafe_i2c_access){
+ if( portid_count < I2C_MASTER_CH_7 ||
+ portid_count == I2C_MASTER_CH_9 || portid_count == I2C_MASTER_CH_10 )
+ continue;
+ }
+ i2c_core_deinit(portid_count, fpga_dev.data_base_addr);
+ }
+
+ for (portid_count = 0; portid_count < SFF_PORT_TOTAL; portid_count++) {
+ if (fpga_data->sff_devices[portid_count] != NULL) {
+ rem_data = dev_get_drvdata(fpga_data->sff_devices[portid_count]);
+ device_unregister(fpga_data->sff_devices[portid_count]);
+ put_device(fpga_data->sff_devices[portid_count]);
+ kfree(rem_data);
+ }
+ }
+
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ sysfs_remove_group(&sff_dev->kobj, &sff_led_test_grp);
+ kobject_put(fpga);
+ kobject_put(cpld1);
+ kobject_put(cpld2);
+ device_destroy(fpgafwclass, MKDEV(0, 0));
+ devm_kfree(&pdev->dev, fpga_data);
+ return 0;
+}
+
+static struct platform_driver fishbone2_drv = {
+ .probe = fishbone2_drv_probe,
+ .remove = __exit_p(fishbone2_drv_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+};
+
+#ifdef TEST_MODE
+#define FPGA_PCI_BAR_NUM 2
+#else
+#define FPGA_PCI_BAR_NUM 0
+#endif
+
+
+
+static const struct pci_device_id fpga_id_table[] = {
+ { PCI_VDEVICE(XILINX, FPGA_PCIE_DEVICE_ID) },
+ { PCI_VDEVICE(TEST, TEST_PCIE_DEVICE_ID) },
+ {0, }
+};
+
+MODULE_DEVICE_TABLE(pci, fpga_id_table);
+
+static int fpga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ int err;
+ struct device *dev = &pdev->dev;
+ uint32_t fpga_version;
+
+ if ((err = pci_enable_device(pdev))) {
+ dev_err(dev, "pci_enable_device probe error %d for device %s\n",
+ err, pci_name(pdev));
+ return err;
+ }
+
+ if ((err = pci_request_regions(pdev, FPGA_PCI_NAME)) < 0) {
+ dev_err(dev, "pci_request_regions error %d\n", err);
+ goto pci_disable;
+ }
+
+ /* bar0: data mmio region */
+ fpga_dev.data_mmio_start = pci_resource_start(pdev, FPGA_PCI_BAR_NUM);
+ fpga_dev.data_mmio_len = pci_resource_len(pdev, FPGA_PCI_BAR_NUM);
+ fpga_dev.data_base_addr = ioremap_nocache(fpga_dev.data_mmio_start, fpga_dev.data_mmio_len);
+ if (!fpga_dev.data_base_addr) {
+ dev_err(dev, "cannot iomap region of size %lu\n",
+ (unsigned long)fpga_dev.data_mmio_len);
+ goto pci_release;
+ }
+ dev_info(dev, "data_mmio iomap base = 0x%lx \n",
+ (unsigned long)fpga_dev.data_base_addr);
+ dev_info(dev, "data_mmio_start = 0x%lx data_mmio_len = %lu\n",
+ (unsigned long)fpga_dev.data_mmio_start,
+ (unsigned long)fpga_dev.data_mmio_len);
+
+ printk(KERN_INFO "FPGA PCIe driver probe OK.\n");
+ printk(KERN_INFO "FPGA ioremap registers of size %lu\n", (unsigned long)fpga_dev.data_mmio_len);
+ printk(KERN_INFO "FPGA Virtual BAR %d at %8.8lx - %8.8lx\n", FPGA_PCI_BAR_NUM,
+ (unsigned long)fpga_dev.data_base_addr,
+ (unsigned long)(fpga_dev.data_base_addr + fpga_dev.data_mmio_len));
+ printk(KERN_INFO "");
+ fpga_version = ioread32(fpga_dev.data_base_addr);
+ printk(KERN_INFO "FPGA Version : %8.8x\n", fpga_version);
+ fpgafw_init();
+ platform_device_register(&fishbone2_dev);
+ platform_driver_register(&fishbone2_drv);
+ return 0;
+
+pci_release:
+ pci_release_regions(pdev);
+pci_disable:
+ pci_disable_device(pdev);
+ return -EBUSY;
+}
+
+static void fpga_pci_remove(struct pci_dev *pdev)
+{
+ platform_driver_unregister(&fishbone2_drv);
+ platform_device_unregister(&fishbone2_dev);
+ fpgafw_exit();
+ pci_iounmap(pdev, fpga_dev.data_base_addr);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ printk(KERN_INFO "FPGA PCIe driver remove OK.\n");
+};
+
+static struct pci_driver pci_dev_ops = {
+ .name = FPGA_PCI_NAME,
+ .probe = fpga_pci_probe,
+ .remove = fpga_pci_remove,
+ .id_table = fpga_id_table,
+};
+
+enum {
+ READREG,
+ WRITEREG
+};
+
+struct fpga_reg_data {
+ uint32_t addr;
+ uint32_t value;
+};
+
+static long fpgafw_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
+ int ret = 0;
+ struct fpga_reg_data data;
+ mutex_lock(&fpga_data->fpga_lock);
+
+#ifdef TEST_MODE
+ static uint32_t status_reg;
+#endif
+ // Switch function to read and write.
+ switch (cmd) {
+ case READREG:
+ if (copy_from_user(&data, (void __user*)arg, sizeof(data)) != 0) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EFAULT;
+ }
+ data.value = ioread32(fpga_dev.data_base_addr + data.addr);
+ if (copy_to_user((void __user*)arg , &data, sizeof(data)) != 0) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EFAULT;
+ }
+#ifdef TEST_MODE
+ if (data.addr == 0x1210) {
+ switch (status_reg) {
+ case 0x0000 : status_reg = 0x8000;
+ break;
+
+ case 0x8080 : status_reg = 0x80C0;
+ break;
+ case 0x80C0 : status_reg = 0x80F0;
+ break;
+ case 0x80F0 : status_reg = 0x80F8;
+ break;
+
+ }
+ iowrite32(status_reg, fpga_dev.data_base_addr + 0x1210);
+ }
+#endif
+
+
+ break;
+ case WRITEREG:
+ if (copy_from_user(&data, (void __user*)arg, sizeof(data)) != 0) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EFAULT;
+ }
+ iowrite32(data.value, fpga_dev.data_base_addr + data.addr);
+
+#ifdef TEST_MODE
+ if (data.addr == 0x1204) {
+ status_reg = 0x8080;
+ iowrite32(status_reg, fpga_dev.data_base_addr + 0x1210);
+ }
+#endif
+
+ break;
+ default:
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ mutex_unlock(&fpga_data->fpga_lock);
+ return ret;
+}
+
+
+const struct file_operations fpgafw_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = fpgafw_unlocked_ioctl,
+};
+
+
+static int fpgafw_init(void) {
+ printk(KERN_INFO "Initializing the switchboard driver\n");
+ // Try to dynamically allocate a major number for the device -- more difficult but worth it
+ majorNumber = register_chrdev(0, DEVICE_NAME, &fpgafw_fops);
+ if (majorNumber < 0) {
+ printk(KERN_ALERT "Failed to register a major number\n");
+ return majorNumber;
+ }
+ printk(KERN_INFO "Device registered correctly with major number %d\n", majorNumber);
+
+ // Register the device class
+ fpgafwclass = class_create(THIS_MODULE, CLASS_NAME);
+ if (IS_ERR(fpgafwclass)) { // Check for error and clean up if there is
+ unregister_chrdev(majorNumber, DEVICE_NAME);
+ printk(KERN_ALERT "Failed to register device class\n");
+ return PTR_ERR(fpgafwclass);
+ }
+ printk(KERN_INFO "Device class registered correctly\n");
+
+ // Register the device driver
+ fpgafwdev = device_create(fpgafwclass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
+ if (IS_ERR(fpgafwdev)) { // Clean up if there is an error
+ class_destroy(fpgafwclass); // Repeated code but the alternative is goto statements
+ unregister_chrdev(majorNumber, DEVICE_NAME);
+ printk(KERN_ALERT "Failed to create the FW upgrade device node\n");
+ return PTR_ERR(fpgafwdev);
+ }
+ printk(KERN_INFO "FPGA fw upgrade device node created correctly\n");
+ return 0;
+}
+
+static void fpgafw_exit(void) {
+ device_destroy(fpgafwclass, MKDEV(majorNumber, 0)); // remove the device
+ class_unregister(fpgafwclass); // unregister the device class
+ class_destroy(fpgafwclass); // remove the device class
+ unregister_chrdev(majorNumber, DEVICE_NAME); // unregister the major number
+ printk(KERN_INFO "Goodbye!\n");
+}
+
+int fishbone2_init(void)
+{
+ int rc;
+ rc = pci_register_driver(&pci_dev_ops);
+ if (rc)
+ return rc;
+ return 0;
+}
+
+void fishbone2_exit(void)
+{
+ pci_unregister_driver(&pci_dev_ops);
+}
+
+module_init(fishbone2_init);
+module_exit(fishbone2_exit);
+
+module_param(allow_unsafe_i2c_access, bool, 0400);
+MODULE_PARM_DESC(allow_unsafe_i2c_access, "enable i2c busses despite potential races against BMC bus access");
+
+MODULE_AUTHOR("Pradchaya P. ");
+MODULE_DESCRIPTION("Celestica Fishbone2 switchboard platform driver");
+MODULE_VERSION(MOD_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-cel/shamu/scripts/platform_sensors.py
new file mode 100755
index 000000000000..186ee6c5450e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/scripts/platform_sensors.py
@@ -0,0 +1,173 @@
+#!/usr/bin/python
+#
+# Silverstone platform sensors. This script get the sensor data from BMC
+# using ipmitool and display them in lm-sensor alike format.
+#
+# The following data is support:
+# 1. Temperature sensors
+# 2. PSUs
+# 3. Fan trays
+
+import sys
+import logging
+import subprocess
+
+IPMI_SDR_CMD = "ipmitool sdr elist"
+MAX_NUM_FANS = 7
+MAX_NUM_PSUS = 2
+
+
+def ipmi_sensor_dump(cmd):
+ ''' Execute ipmitool command return dump output
+ exit if any error occur.
+ '''
+ sensor_dump = ''
+ try:
+ sensor_dump = subprocess.check_output(cmd, shell=True)
+ except subprocess.CalledProcessError as e:
+ logging.error('Error! Failed to execute: {}'.format(cmd))
+ sys.exit(1)
+ return sensor_dump
+
+def get_reading_by_name(sensor_name, sdr_elist_dump):
+ '''
+ Search for the match sensor name, return sensor
+ reading value and unit, return object epmtry string
+ if search not match.
+
+ The output of sensor dump:
+ TEMP_FAN_U52 | 00h | ok | 7.1 | 31 degrees C
+ TEMP_FAN_U17 | 01h | ok | 7.1 | 27 degrees C
+ TEMP_SW_U52 | 02h | ok | 7.1 | 30 degrees C
+ Fan2_Status | 07h | ok | 29.2 | Present
+ Fan2_Front | 0Eh | ok | 29.2 | 12000 RPM
+ Fan2_Rear | 46h | ok | 29.2 | 14700 RPM
+ PSU2_Status | 39h | ok | 10.2 | Presence detected
+ PSU2_Fan | 3Dh | ok | 10.2 | 16000 RPM
+ PSU2_VIn | 3Ah | ok | 10.2 | 234.30 Volts
+ PSU2_CIn | 3Bh | ok | 10.2 | 0.80 Amps
+ '''
+ found = ''
+
+ for line in sdr_elist_dump.split("\n"):
+ if sensor_name in line:
+ found = line.strip()
+ break
+
+ if not found:
+ logging.error('Cannot find sensor name:' + sensor_name)
+
+ else:
+ try:
+ found = found.split('|')[4]
+ except IndexError:
+ logging.error('Cannot get sensor data of:' + sensor_name)
+
+ logging.basicConfig(level=logging.DEBUG)
+ return found
+
+
+def read_temperature_sensors(ipmi_sdr_elist):
+
+ sensor_list = [
+ ('TEMP_FAN_U52', 'Fan Tray Middle Temp'),
+ ('TEMP_FAN_U17', 'Fan Tray Right Temp'),
+ ('TEMP_SW_U52', 'Switchboard Left Inlet Temp'),
+ ('TEMP_SW_U16', 'Switchboard Right Inlet Temp'),
+ ('TEMP_BB_U3', 'Baseboard Temp'),
+ ('TEMP_CPU', 'CPU Internal Temp'),
+ ('TEMP_SW_Internal', 'ASIC Internal Temp'),
+ ('SW_U04_Temp', 'IR3595 Chip Left Temp'),
+ ('SW_U14_Temp', 'IR3595 Chip Right Temp'),
+ ('SW_U4403_Temp', 'IR3584 Chip Temp'),
+ ]
+
+ output = ''
+ sensor_format = '{0:{width}}{1}\n'
+ # Find max length of sensor calling name
+ max_name_width = max(len(sensor[1]) for sensor in sensor_list)
+
+ output += "Temperature Sensors\n"
+ output += "Adapter: IPMI adapter\n"
+ for sensor in sensor_list:
+ reading = get_reading_by_name(sensor[0],ipmi_sdr_elist)
+ output += sensor_format.format('{}:'.format(sensor[1]),
+ reading,
+ width=str(max_name_width+1))
+ output += '\n'
+ return output
+
+
+def read_fan_sensors(num_fans, ipmi_sdr_elist):
+
+ sensor_list = [
+ ('Fan{}_Status', 'Status'),
+ ('Fan{}_Front', 'Fan {} front'),
+ ('Fan{}_Rear', 'Fan {} rear'),
+ ]
+
+ output = ''
+ sensor_format = '{0:{width}}{1}\n'
+ # Find max length of sensor calling name
+ max_name_width = max(len(sensor[1]) for sensor in sensor_list)
+
+ output += "Fan Trays\n"
+ output += "Adapter: IPMI adapter\n"
+ for fan_num in range(1, num_fans+1):
+ for sensor in sensor_list:
+ ipmi_sensor_name = sensor[0].format(fan_num)
+ display_sensor_name = sensor[1].format(fan_num)
+ reading = get_reading_by_name(ipmi_sensor_name, ipmi_sdr_elist)
+ output += sensor_format.format('{}:'.format(display_sensor_name),
+ reading,
+ width=str(max_name_width+1))
+ output += '\n'
+ return output
+
+
+def read_psu_sensors(num_psus, ipmi_sdr_elist):
+
+ sensor_list = [
+ ('PSU{}_Status', 'PSU {} Status'),
+ ('PSU{}_Fan', 'PSU {} Fan'),
+ ('PSU{}_VIn', 'PSU {} Input Voltag'),
+ ('PSU{}_CIn', 'PSU {} Input Current'),
+ ('PSU{}_PIn', 'PSU {} Input Power'),
+ ('PSU{}_Temp1', 'PSU {} Temp1'),
+ ('PSU{}_Temp2', 'PSU {} Temp2'),
+ ('PSU{}_VOut', 'PSU {} Output Voltag'),
+ ('PSU{}_COut', 'PSU {} Output Current'),
+ ('PSU{}_POut', 'PSU {} Output Power'),
+ ]
+
+ output = ''
+ sensor_format = '{0:{width}}{1}\n'
+ # Find max length of sensor calling name
+ max_name_width = max(len(sensor[1]) for sensor in sensor_list)
+
+ output += "PSU\n"
+ output += "Adapter: IPMI adapter\n"
+ for psu_num in range(1, num_psus+1):
+ for sensor in sensor_list:
+ ipmi_sensor_name = sensor[0].format(psu_num)
+ display_sensor_name = sensor[1].format(psu_num)
+ reading = get_reading_by_name(ipmi_sensor_name, ipmi_sdr_elist)
+ output += sensor_format.format('{}:'.format(display_sensor_name),
+ reading,
+ width=str(max_name_width+1))
+ output += '\n'
+ return output
+
+
+def main():
+ output_string = ''
+
+ ipmi_sdr_elist = ipmi_sensor_dump(IPMI_SDR_CMD)
+ output_string += read_temperature_sensors(ipmi_sdr_elist)
+ output_string += read_psu_sensors(MAX_NUM_PSUS, ipmi_sdr_elist)
+ output_string += read_fan_sensors(MAX_NUM_FANS, ipmi_sdr_elist)
+ print(output_string)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/scripts/sensors b/platform/broadcom/sonic-platform-modules-cel/shamu/scripts/sensors
new file mode 100755
index 000000000000..405d92c2b3cc
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/scripts/sensors
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+DOCKER_EXEC_FLAGS="i"
+
+# Determine whether stdout is on a terminal
+if [ -t 1 ] ; then
+ DOCKER_EXEC_FLAGS+="t"
+fi
+
+docker exec -$DOCKER_EXEC_FLAGS pmon sensors "$@"
+docker exec -$DOCKER_EXEC_FLAGS pmon platform_sensors.py "$@"
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/setup.py b/platform/broadcom/sonic-platform-modules-cel/shamu/setup.py
new file mode 100644
index 000000000000..20a2b6d1063a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/setup.py
@@ -0,0 +1,34 @@
+from setuptools import setup
+
+DEVICE_NAME = 'celestica'
+HW_SKU = 'x86_64-cel_silverstone-r0'
+
+setup(
+ name='sonic-platform',
+ version='1.0',
+ description='SONiC platform API implementation on Celestica Platforms',
+ license='Apache 2.0',
+ author='SONiC Team',
+ author_email='linuxnetdev@microsoft.com',
+ url='https://github.com/Azure/sonic-buildimage',
+ maintainer='Wirut Getbamrung',
+ maintainer_email='wgetbumr@celestica.com',
+ packages=[
+ 'sonic_platform',
+ ],
+ package_dir={
+ 'sonic_platform': '../../../../device/{}/{}/sonic_platform'.format(DEVICE_NAME, HW_SKU)},
+ classifiers=[
+ 'Development Status :: 3 - Alpha',
+ 'Environment :: Plugins',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Information Technology',
+ 'Intended Audience :: System Administrators',
+ 'License :: OSI Approved :: Apache Software License',
+ 'Natural Language :: English',
+ 'Operating System :: POSIX :: Linux',
+ 'Programming Language :: Python :: 2.7',
+ 'Topic :: Utilities',
+ ],
+ keywords='sonic SONiC platform PLATFORM',
+)
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/sonic_platform.egg-info/PKG-INFO b/platform/broadcom/sonic-platform-modules-cel/shamu/sonic_platform.egg-info/PKG-INFO
new file mode 100644
index 000000000000..48ce1ea303bb
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/sonic_platform.egg-info/PKG-INFO
@@ -0,0 +1,23 @@
+Metadata-Version: 1.2
+Name: sonic-platform
+Version: 1.0
+Summary: SONiC platform API implementation on Celestica Platforms
+Home-page: https://github.com/Azure/sonic-buildimage
+Author: SONiC Team
+Author-email: linuxnetdev@microsoft.com
+Maintainer: Wirut Getbamrung
+Maintainer-email: wgetbumr@celestica.com
+License: Apache 2.0
+Description: UNKNOWN
+Keywords: sonic SONiC platform PLATFORM
+Platform: UNKNOWN
+Classifier: Development Status :: 3 - Alpha
+Classifier: Environment :: Plugins
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Information Technology
+Classifier: Intended Audience :: System Administrators
+Classifier: License :: OSI Approved :: Apache Software License
+Classifier: Natural Language :: English
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Topic :: Utilities
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/sonic_platform.egg-info/SOURCES.txt b/platform/broadcom/sonic-platform-modules-cel/shamu/sonic_platform.egg-info/SOURCES.txt
new file mode 100644
index 000000000000..f14add75ab6f
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/sonic_platform.egg-info/SOURCES.txt
@@ -0,0 +1,11 @@
+setup.py
+../../../../device/celestica/x86_64-cel_silverstone-r0/sonic_platform/__init__.py
+../../../../device/celestica/x86_64-cel_silverstone-r0/sonic_platform/chassis.py
+../../../../device/celestica/x86_64-cel_silverstone-r0/sonic_platform/eeprom.py
+../../../../device/celestica/x86_64-cel_silverstone-r0/sonic_platform/fan.py
+../../../../device/celestica/x86_64-cel_silverstone-r0/sonic_platform/helper.py
+../../../../device/celestica/x86_64-cel_silverstone-r0/sonic_platform/platform.py
+sonic_platform.egg-info/PKG-INFO
+sonic_platform.egg-info/SOURCES.txt
+sonic_platform.egg-info/dependency_links.txt
+sonic_platform.egg-info/top_level.txt
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/sonic_platform.egg-info/dependency_links.txt b/platform/broadcom/sonic-platform-modules-cel/shamu/sonic_platform.egg-info/dependency_links.txt
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/sonic_platform.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/sonic_platform.egg-info/top_level.txt b/platform/broadcom/sonic-platform-modules-cel/shamu/sonic_platform.egg-info/top_level.txt
new file mode 100644
index 000000000000..82b4b6958796
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/sonic_platform.egg-info/top_level.txt
@@ -0,0 +1 @@
+sonic_platform
diff --git a/platform/broadcom/sonic-platform-modules-cel/shamu/systemd/platform-modules-shamu.service b/platform/broadcom/sonic-platform-modules-cel/shamu/systemd/platform-modules-shamu.service
new file mode 100644
index 000000000000..236eba0bd5ec
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/shamu/systemd/platform-modules-shamu.service
@@ -0,0 +1,14 @@
+
+[Unit]
+Description=Celestica shamu platform modules
+After=local-fs.target
+Before=pmon.service
+
+[Service]
+Type=oneshot
+ExecStart=-/etc/init.d/platform-modules-shamu start
+ExecStop=-/etc/init.d/platform-modules-shamu stop
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/afulnx_64 b/platform/broadcom/sonic-platform-modules-cel/tools/afulnx_64
deleted file mode 100755
index c32823393c08..000000000000
Binary files a/platform/broadcom/sonic-platform-modules-cel/tools/afulnx_64 and /dev/null differ
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/bmc_wdt/bmc_wdt.py b/platform/broadcom/sonic-platform-modules-cel/tools/bmc_wdt/bmc_wdt.py
new file mode 100644
index 000000000000..e22d96326b76
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/bmc_wdt/bmc_wdt.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+
+#############################################################################
+# #
+# Service to control CPU watchdog #
+# #
+#############################################################################
+
+import os
+import time
+import logging
+import logging.handlers
+import requests
+import argparse
+import subprocess
+
+HEARTBEAT_TIME = 20
+MAX_FILE_COUNT = 3
+WDT_TIMEOUT = 60
+MAX_LOG_BYTES = 20 * 1000000
+HOSTNAME = "240.1.1.1"
+WDT_URL = "http://240.1.1.1:8080/api/sys/watchdog"
+BMC_WDT_LOG = '/var/log/bmc_feed_watchdog.log'
+
+
+lh = logging.handlers.RotatingFileHandler(
+ filename=BMC_WDT_LOG, maxBytes=MAX_LOG_BYTES, backupCount=MAX_FILE_COUNT)
+formatter = logging.Formatter(
+ fmt='%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%b %d %H:%M:%S')
+lh.setFormatter(formatter)
+logger = logging.getLogger('bmc_feed_watchdog')
+logger.addHandler(lh)
+logger.setLevel(logging.INFO)
+
+
+def set_wdt_timeout(timeout):
+ data = dict()
+ data["wdt"] = str(timeout)
+ status_code = -1
+ message = None
+ try:
+ res = requests.post(WDT_URL, json=data, timeout=5)
+ status_code = res.status_code
+ message = res.json().get('result')
+ except:
+ message = "Unable set watchdog timeout"
+
+ return status_code, message
+
+
+def ping():
+ try:
+ response = subprocess.check_output(
+ ['ping', '-c', '3', HOSTNAME],
+ stderr=subprocess.STDOUT,
+ universal_newlines=True
+ )
+ except subprocess.CalledProcessError:
+ response = None
+ return response != None
+
+
+def start():
+ logger.info("Started CPU watchdog")
+ error_flag = 1
+ status_code = -1
+ while True:
+ status_code, message = set_wdt_timeout(WDT_TIMEOUT)
+
+ # Error checking
+ if status_code == 200 and message != 'success':
+ logger.error(message)
+ error_flag = 1
+ elif status_code != 200 and not ping():
+ logger.error("Unable to connect to BMC")
+ error_flag = 1
+ elif status_code != 200 and ping():
+ if not error_flag:
+ logger.error(message)
+ time.sleep(1)
+ error_flag = 1
+ continue
+
+ # Pass error
+ if error_flag and status_code == 200 and message == 'success':
+ error_flag = 0
+ logger.info("BMC connection successful")
+
+ time.sleep(HEARTBEAT_TIME)
+
+
+def stop():
+ logger.info("Stopping CPU watchdog")
+ status_code = -1
+ while status_code != 200:
+ status_code, message = set_wdt_timeout(0)
+ if status_code == 200 and message != 'success':
+ logger.error(message)
+ elif status_code != 200 and not ping():
+ logger.error("Unable to connect to BMC")
+ elif ping():
+ time.sleep(1)
+ continue
+
+ logger.info("Stopped CPU watchdog")
+
+
+def main():
+ parser = argparse.ArgumentParser(description='')
+ parser.add_argument('option', choices=["start", "stop"])
+ args = parser.parse_args()
+ if args.option == "start":
+ start()
+ stop()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/bmc_wdt/bmc_wdt.service b/platform/broadcom/sonic-platform-modules-cel/tools/bmc_wdt/bmc_wdt.service
new file mode 100755
index 000000000000..88c3b5ceb44b
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/bmc_wdt/bmc_wdt.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Service for enable BMC watchdog.
+After=bmc_vlan.service
+
+[Service]
+ExecStart=/usr/bin/python /usr/local/etc/bmc_wdt.py start
+ExecStop=/usr/bin/python /usr/local/etc/bmc_wdt.py stop
+
+[Install]
+WantedBy=multi-user.target
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/bmcutil/bmc-exec b/platform/broadcom/sonic-platform-modules-cel/tools/bmcutil/bmc-exec
new file mode 100755
index 000000000000..14435e857ff9
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/bmcutil/bmc-exec
@@ -0,0 +1,45 @@
+#!/bin/bash
+#
+# Copyright 2019-present Celestica. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+#
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+
+command="$@"
+
+usage() {
+ echo "Usage: bmc-exec "
+ echo
+}
+
+run_cmd() {
+ echo "Run command: "$command
+ echo
+ ret=$(curl -m 5 --silent --header "Content-Type:application/json" -d "{\"data\": \"${command}\"}" http://240.1.1.1:8080/api/sys/raw)
+ if [ -z "$ret" ];
+ then
+ echo "Failed to connect on BMC"
+ else
+ echo $ret | python -c "import sys, json; k = json.load(sys.stdin)['result']; print k if type(k) is not list else '\n'.join(k);"
+ fi
+ return 0
+}
+
+if [ $# -lt 1 ]; then
+ usage
+ exit -1
+else
+ run_cmd
+fi
+
+exit $?
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/bmcutil/bmcpwd b/platform/broadcom/sonic-platform-modules-cel/tools/bmcutil/bmcpwd
new file mode 100644
index 000000000000..3e24c6b13536
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/bmcutil/bmcpwd
@@ -0,0 +1 @@
+kt3I0K_QxQ==
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/bmcutil/bmcutil.py b/platform/broadcom/sonic-platform-modules-cel/tools/bmcutil/bmcutil.py
new file mode 100644
index 000000000000..7edc55ac8862
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/bmcutil/bmcutil.py
@@ -0,0 +1,296 @@
+#!/usr/bin/python
+
+"""
+bmcutil.py
+BMC utility, implements management functions provided by BMC RESTful APIs.
+"""
+
+import requests
+import re
+import hashlib
+import binascii
+import os
+import base64
+
+
+# Base class of BmcUtil
+class BmcUtilBase(object):
+ def __init__(self):
+ self.bmc_info_url = "http://240.1.1.1:8080/api/sys/bmc"
+ self.bmc_eth_info_url = "http://240.1.1.1:8080/api/sys/eth"
+ self.bmc_raw_command_url = "http://240.1.1.1:8080/api/sys/raw"
+ self.bmc_pwd_url = "http://240.1.1.1:8080/api/sys/userpassword"
+ self.bmc_pwd_path = "/usr/local/etc/bmcpwd"
+ self.bmc_syslog_url = "http://240.1.1.1:8080/api/sys/syslog"
+
+ def request_data(self, url):
+ # Reqest data from BMC if not exist.
+ data_req = requests.get(url)
+ data_json = data_req.json()
+ data_list = data_json.get('Information')
+ return data_list
+
+ def save_bmc_password(self, clear_pwd):
+ enc = []
+ key = "bmc"
+ for i in range(len(clear_pwd)):
+ key_c = key[i % len(key)]
+ enc_c = chr((ord(clear_pwd[i]) + ord(key_c)) % 256)
+ enc.append(enc_c)
+ enc_pwd = base64.urlsafe_b64encode("".join(enc))
+
+ with open(self.bmc_pwd_path, 'w') as file:
+ file.write(enc_pwd)
+
+ def get_bmc_pass(self):
+ with open(self.bmc_pwd_path) as file:
+ data = file.read()
+
+ key = "bmc"
+ dec = []
+ enc = base64.urlsafe_b64decode(data)
+ for i in range(len(enc)):
+ key_c = key[i % len(key)]
+ dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
+ dec.append(dec_c)
+ return "".join(dec)
+
+ def version(self):
+ """
+ Return version information string
+ @return version string of BMC OS
+ """
+ bmc_version = None
+
+ bmc_version_key = "OpenBMC Version"
+ bmc_info = self.request_data(self.bmc_info_url)
+ bmc_version = bmc_info.get(bmc_version_key)
+
+ return str(bmc_version)
+
+ def set_eth0_addr(self, ip_addr, mask):
+ """
+ Set eth0 IPv4 address
+ @ip_addr MANDATORY, IPv4 ip address string
+ @mask MANDATORY, IPv4 network mask string
+ """
+
+ json_data = dict()
+ json_data["data"] = "ifconfig eth0 %s netmask %s up" % (ip_addr, mask)
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ return False
+ return True
+
+ def get_eth0_addr_list(self):
+ """
+ Get eth0 IPv4 address
+ @return a list of (IPv4 ip address/mask string)
+ """
+ ipv4_adress = []
+ eth_data_list = self.request_data(self.bmc_eth_info_url)
+
+ for eth_data in eth_data_list:
+ if 'inet addr' in eth_data:
+ ipv4_list = re.findall(r'[0-9]+(?:\.[0-9]+){3}', eth_data)
+ if len(ipv4_list) == 3:
+ ipv4 = ipv4_list[0] + "/" + ipv4_list[2]
+ ipv4_adress.append(ipv4)
+
+ return str(ipv4_adress)
+
+ def set_gateway_ip(self, gw_ip):
+ """
+ Set gateway IPv4 address string
+ @gw_ip MANATORY, IPv4 address of gateway
+ """
+
+ json_data = dict()
+ json_data["data"] = "route del default"
+
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ return False
+
+ json_data["data"] = "route add default gw %s" % gw_ip
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ return False
+
+ return True
+
+ def get_gateway_ip(self):
+ """
+ Get gateway IPv4 address string
+ @return IPv4 address of gateway
+ """
+
+ default_gw = None
+
+ json_data = dict()
+ json_data["data"] = "route"
+
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code == 200:
+ data_list = r.json().get('result')
+ for raw_data in data_list:
+ if 'default' in raw_data:
+ route_data = raw_data.split()
+ default_gw = route_data[1] if len(route_data) > 0 else None
+
+ return str(default_gw)
+
+ def set_user_and_passwd(self, user_name, password):
+ """
+ Set BMC user name and password
+ @user_name MANDATORY, BMC user
+ @password MANDATORY, BMC user's password
+ """
+ json_data = dict()
+ json_data["user"] = str(user_name)
+ json_data["oldpassword"] = self.get_bmc_pass()
+ json_data["newpassword"] = password
+ r = requests.post(self.bmc_pwd_url, json=json_data)
+ return_data = r.json()
+
+ if r.status_code != 200 or 'success' not in return_data.get('result'):
+ return False
+
+ self.save_bmc_password(password)
+ return True
+
+ def add_syslog_server(self, svr_ip, svr_port):
+ """
+ Add syslog server for BMC
+ @svr_ip MANDATORY, syslog server IP string
+ @svr_port MANDATORY, syslog server destination port
+ """
+ json_data = dict()
+ json_data["addr"] = str(svr_ip)
+ json_data["port"] = str(svr_port)
+ r = requests.post(self.bmc_syslog_url, json=json_data)
+ if r.status_code != 200 or 'success' not in r.json().get('result'):
+ return False
+ return True
+
+ def get_syslog_server_list(self):
+ """
+ # Get syslog server list of BMC
+ # @return a list of syslog server ip and destination port pair
+ """
+ syslog_ip = None
+ syslog_port = None
+
+ json_data = dict()
+ json_data["data"] = "tail -n 1 /etc/rsyslog.conf"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ return False
+
+ return_data = r.json()
+ result = return_data.get("result")
+ ip = re.findall(r'[0-9]+(?:\.[0-9]+){3}', result[0])
+ port = str(result[0]).split(":")
+ syslog_ip = ip[0] if len(ip) > 0 else None
+ syslog_port = port[1] if len(port) > 1 else None
+
+ return [syslog_ip, syslog_port]
+
+ def del_syslog_server(self, svr_ip, svr_port):
+ """
+ Delete syslog server for BMC
+ @svr_ip MANDATORY, syslog server IP string
+ @svr_port MANDATORY, syslog server destination port
+ """
+ json_data = dict()
+ json_data["addr"] = "127.0.0.1"
+ json_data["port"] = str(svr_port)
+ r = requests.post(self.bmc_syslog_url, json=json_data)
+ if r.status_code != 200 or 'success' not in r.json().get('result'):
+ return False
+ return True
+
+ def get_bmc_system_state(self):
+ """
+ Get BMC system state, includes CPU, memory, storage
+ MUST contains status of: CPU, memory, disk
+ dict object:
+ {
+ "CPU": {
+ "StateOutputs": "output of command 'top -bn 1'"
+ "Usage": "10.0"
+ },
+ "MEMORY": {
+ "StateOutputs": "output of command 'free -m'"
+ "Usage": "15.0" # caculate: "free -t | grep \"buffers/cache\" | awk '{ printf \"mem usage : %.1f%%\\n\",$3/($3+$4) * 100}'"
+ },
+ "DISK": {
+ "StateOutput": "output of command 'df -h'"
+ "Usage": "12.5"
+ }
+ }
+ """
+
+ state_data = dict()
+ bmc_info = self.request_data(self.bmc_info_url)
+
+ cpu_key = "CPU Usage"
+ cpu_data_raw = bmc_info.get(cpu_key)
+ cpu_usage = cpu_data_raw.split()[1].strip('%')
+ cpu_data = dict()
+ cpu_data["StateOutputs"] = "output of command 'top -bn 1'"
+ cpu_data["Usage"] = "{:.1f}".format(float(cpu_usage))
+ state_data["CPU"] = cpu_data
+
+ disk_key = "Disk Usage"
+ disk_data_raw = bmc_info.get(disk_key)
+ disk_usage = disk_data_raw.split()[7].strip('%')
+ disk_data = dict()
+ disk_data["StateOutputs"] = "output of command 'df -h'"
+ disk_data["Usage"] = "{:.1f}".format(float(disk_usage))
+ state_data["DISK"] = disk_data
+
+ json_data = dict()
+ json_data["data"] = "free -t"
+ mem_usage = "None"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code == 200:
+ mem_data_raw = r.json().get('result')[2]
+ mem_u = float(mem_data_raw.split()[2])
+ mem_f = float(mem_data_raw.split()[3])
+ mem_usage = (mem_u/(mem_u+mem_f)) * 100
+ mem_data = dict()
+ mem_data["StateOutputs"] = "output of command 'free -t'"
+ mem_data["Usage"] = "{:.1f}".format(mem_usage)
+ state_data["MEMORY"] = mem_data
+
+ return state_data
+
+ def reboot_bmc(self):
+ """
+ Reboot BMC
+ """
+ json_data = dict()
+ json_data["data"] = "reboot"
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ return False
+
+ return True
+
+ def set_location_led(self, admin_state):
+ """
+ Enable/disable location LED
+ @admin_state MANDATORY, should be string "on" or "off"
+ """
+
+ json_data = dict()
+ if str(admin_state).lower() not in ["on", "off"]:
+ return False
+
+ json_data["data"] = "led_location.sh %s" % admin_state
+ r = requests.post(self.bmc_raw_command_url, json=json_data)
+ if r.status_code != 200:
+ return False
+
+ return True
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/fpga_prog/fpga_prog b/platform/broadcom/sonic-platform-modules-cel/tools/fpga_prog/fpga_prog
new file mode 100755
index 000000000000..edf7916e58b7
Binary files /dev/null and b/platform/broadcom/sonic-platform-modules-cel/tools/fpga_prog/fpga_prog differ
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/fpga_prog/fpga_prog.c b/platform/broadcom/sonic-platform-modules-cel/tools/fpga_prog/fpga_prog.c
new file mode 100644
index 000000000000..c640c8ad0064
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/fpga_prog/fpga_prog.c
@@ -0,0 +1,282 @@
+/********************************************************************
+Author: Sittisak Sinprem
+ flash_spi_fpga
+
+ user-space appliction to flash SPI FLASH
+
+ As a "root" previledge, this program can run well
+ while other user group would report system errors under Linux OS.
+
+*********************************************************************/
+
+#include
+#include
+#include
+#include //for open()
+#include //for close()
+#include
+#include
+
+/**
+ * The FPGA SPI Flash update application
+ * This application read the binary image file and program
+ * into flash memory. The erasing time can be long the
+ * the WAIT_WRITE_READY_SEC should be more than 30 seconds.
+ */
+
+#define WAIT_WRITE_READY_SEC 180
+#define WAIT_WRITE_CONTINUE_CYCLE 100000
+
+#define REG_SPI_WR_EN 0x1200
+#define REG_SPI_WR_DAT 0x1204
+#define REG_SPI_CHK_ID 0x1208
+#define REG_SPI_VERIFY 0x120C
+#define REG_SPI_STAT 0x1210
+#define REG_SPI_RESET 0x1214
+
+#define SPI_STAT_MARK_READY (1 << 15)
+#define SPI_STAT_MARK_DONE (1 << 14)
+#define SPI_STAT_MARK_ERROR_ANY (1 << 13)
+#define SPI_STAT_MARK_ERROR_CHKID (1 << 12)
+#define SPI_STAT_MARK_ERROR_ERASE (1 << 11)
+#define SPI_STAT_MARK_ERROR_PROG (1 << 10)
+#define SPI_STAT_MARK_ERROR_TOUT (1 << 9)
+#define SPI_STAT_MARK_ERROR_CRC (1 << 8)
+#define SPI_STAT_MARK_STG_STARTED (1 << 7)
+#define SPI_STAT_MARK_STG_INITED (1 << 6)
+#define SPI_STAT_MARK_STG_CHECKED_ID (1 << 5)
+#define SPI_STAT_MARK_STG_ERSD_SW (1 << 4)
+#define SPI_STAT_MARK_STG_UP_ERSD_IMG (1 << 3)
+#define SPI_STAT_MARK_STG_UP_PRG_IMG (1 << 2)
+#define SPI_STAT_MARK_STG_VERIFIED (1 << 1)
+#define SPI_STAT_MARK_STG_PRG_CMPT (1 << 0)
+
+#define debug(fmt,args...) printf("debug : "fmt"\n",##args)
+#define reg_write(reg,value) func_write(reg,value)
+#define reg_read(reg,value) value = func_read(reg)
+
+#define DEV_CHAR_FILENAME "/dev/fwupgrade"
+
+struct fpga_reg_data {
+ uint32_t reg;
+ uint32_t value;
+};
+
+enum{
+ READREG,
+ WRITEREG
+};
+
+unsigned int func_write(int addr,unsigned long value){
+ int fd;
+ int ret;
+ struct fpga_reg_data fpga_reg;
+
+ fd = open(DEV_CHAR_FILENAME, O_RDWR);
+
+ fpga_reg.reg = addr;
+ fpga_reg.value = value;
+
+ ioctl(fd, WRITEREG, (void *)&fpga_reg);
+
+ close(fd);
+ return 0;
+}
+
+unsigned int func_read(int addr){
+ int fd;
+ int ret;
+
+ struct fpga_reg_data fpga_reg;
+
+ fd = open(DEV_CHAR_FILENAME, O_RDWR);
+
+ fpga_reg.reg = addr;
+
+ ioctl(fd, READREG, (void *)&fpga_reg);
+
+ close(fd);
+ return fpga_reg.value;
+}
+
+void dump_status(int Stat){
+ debug("#########################");
+ debug("%d ready(1)/busy(0)", (Stat&SPI_STAT_MARK_READY)!=0);
+ debug("%d done", (Stat&SPI_STAT_MARK_DONE)!=0);
+ debug("%d error any", (Stat&SPI_STAT_MARK_ERROR_ANY)!=0);
+ debug("%d error checkId", (Stat&SPI_STAT_MARK_ERROR_CHKID)!=0);
+ debug("%d error erase", (Stat&SPI_STAT_MARK_ERROR_ERASE)!=0);
+ debug("%d error program", (Stat&SPI_STAT_MARK_ERROR_PROG)!=0);
+ debug("%d error timeout", (Stat&SPI_STAT_MARK_ERROR_TOUT)!=0);
+ debug("%d error crc", (Stat&SPI_STAT_MARK_ERROR_CRC)!=0);
+ debug("%d stage started", (Stat&SPI_STAT_MARK_STG_STARTED)!=0);
+ debug("%d stage inited", (Stat&SPI_STAT_MARK_STG_INITED)!=0);
+ debug("%d stage checked id", (Stat&SPI_STAT_MARK_STG_CHECKED_ID)!=0);
+ debug("%d stage erasred", (Stat&SPI_STAT_MARK_STG_ERSD_SW)!=0);
+ debug("%d stage upload erase img", (Stat&SPI_STAT_MARK_STG_UP_ERSD_IMG)!=0);
+ debug("%d stage upload program img",(Stat&SPI_STAT_MARK_STG_UP_PRG_IMG)!=0);
+ debug("%d stage verified", (Stat&SPI_STAT_MARK_STG_VERIFIED)!=0);
+ debug("%d stage completed", (Stat&SPI_STAT_MARK_STG_PRG_CMPT)!=0);
+}
+
+int flash_program(char *data,int lens){
+ int ctimeout;
+ int error =0;
+ unsigned long Stat = 0;
+
+ reg_read(REG_SPI_RESET,Stat);
+ printf("Read Reset is %x\n",Stat);
+ printf("Reset Module \n");
+ reg_write(REG_SPI_RESET,0x1); // reset
+ sleep(1);
+ reg_write(REG_SPI_RESET,0x0); // normal mode
+ ctimeout=0;
+ do{ // wait for done flag
+ reg_read(REG_SPI_STAT,Stat);
+ if(Stat & SPI_STAT_MARK_ERROR_ANY){
+ dump_status(Stat);
+ error = Stat;
+ break;
+ }
+ if(ctimeout++ > WAIT_WRITE_READY_SEC){
+ error = Stat| SPI_STAT_MARK_ERROR_TOUT;
+ debug("wait ready timeout . . .");
+ break;
+ }
+ printf(" waiting status to ready ... %d s. status = %x\n",ctimeout,Stat);
+ sleep(1);
+ }while((Stat & 0x80F8) != 0x80F8);
+ if(error){
+ return -1;
+ }
+ printf("Ready\n");
+
+
+ for(int i=0;i WAIT_WRITE_CONTINUE_CYCLE){
+ error = Stat| SPI_STAT_MARK_ERROR_TOUT;
+ debug("wait ready timeout . . .");
+ break;
+ }
+ }while((Stat & 0x80F8) != 0x80F8);
+
+ if(error){
+ printf("FPGA programing fail at %d/%d\n",i,lens);
+ debug("Status = %4.4X",error);
+ break;
+ }
+
+ i +=4;
+
+ if(i%(lens/40*4)==0){
+ printf("FPGA programing . . . %d/%d\n",i,lens);
+ }
+ }
+
+ dump_status(Stat);
+ printf("Status = %4.4X\n",Stat);
+
+ reg_write(REG_SPI_WR_EN,0x0); // write protect
+ reg_write(REG_SPI_RESET,0x1); // module reset
+
+ return error;
+}
+
+int main(int argc,char **argv){
+ FILE *pFILE;
+ int filesize;
+ char *filename;
+ char *fpga_buff;
+ int status;
+ int max_size = 128;
+ int current_size = max_size;
+ int i = 0;
+ int c = EOF;
+
+ printf(" FPGA PROGRAMMNG version 0.1.1 \n");
+ printf(" build date : %s %s\n",__DATE__,__TIME__);
+
+ filename = NULL;
+ filename = malloc(max_size);
+ if(!filename){
+ exit(-12); /* Out of memory */
+ }
+
+ if(argc<2){
+ printf("please enter filename : ");
+ while((c = getchar()) != '\n' && c != EOF ){
+
+ filename[i++] = (char)c;
+ if(i == current_size){
+ current_size += max_size;
+ filename = realloc(filename, current_size);
+ }
+ }
+ filename[i] = '\0';
+ }else{
+ i = strlen(argv[1]) + 1;
+ filename = realloc(filename, i);
+ strcpy(filename, argv[1]);
+ }
+
+ pFILE = fopen(filename,"rb");
+ free(filename);
+ if (pFILE == NULL)
+ {
+ printf("Could not open the file %s, exit\n",filename);
+ return -5;
+ }
+
+ fseek(pFILE , 0 , SEEK_END);
+ filesize = ftell (pFILE);
+ rewind(pFILE);
+ fpga_buff = malloc(filesize);
+ if(fpga_buff==NULL){
+ printf("Can't Allocate memory \n");
+ return -5;
+ }
+
+ fread(fpga_buff,1,filesize,pFILE);
+ fclose(pFILE);
+
+ printf(" Start FPGA Flash ... \n");
+
+ status = flash_program(fpga_buff,filesize);
+
+ if(status == 0){
+ printf(" Programing finish \n");
+ }else{
+ printf(" Program Error : error code %4.4x \n",status);
+ }
+
+ return status;
+}
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/Makefile b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/Makefile
new file mode 100644
index 000000000000..022bcc566c6d
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/Makefile
@@ -0,0 +1,25 @@
+CC = gcc
+AR = ar
+CFLAGS = -Wall -W -Wunused -lpthread -g -O2 -ggdb
+#LFLAGS = -lm -pthread -DVME_DEBUG
+LFLAGS = -lm -pthread
+DEL_FILE = rm -f
+MV_FILE = mv -f
+OBJ_FILE_NODE = ./*.o
+#VPATH =
+INCPATH = -I../include/
+TARGET = ispvm
+
+OBJECTS += hardware.o ispvm_ui.o ivm_core.o
+
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+$(TARGET):$(OBJECTS)
+ $(CC) $(LFLAGS) -o $(TARGET) $(OBJECTS)
+
+clean:
+ -$(DEL_FILE) $(TARGET)
+ -$(DEL_FILE) $(OBJ_FILE_NODE)
+
+
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/hardware.c b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/hardware.c
new file mode 100644
index 000000000000..7a4d5f5456d3
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/hardware.c
@@ -0,0 +1,409 @@
+/*********************************************************************************
+* Lattice Semiconductor Corp. Copyright 2000-2008
+*
+* This is the hardware.c of ispVME V12.1 for JTAG programmable devices.
+* All the functions requiring customization are organized into this file for
+* the convinience of porting.
+*********************************************************************************/
+/*********************************************************************************
+ * Revision History:
+ *
+ * 09/11/07 NN Type cast mismatch variables
+ * 09/24/07 NN Added calibration function.
+ * Calibration will help to determine the system clock frequency
+ * and the count value for one micro-second delay of the target
+ * specific hardware.
+ * Modified the ispVMDelay function
+ * Removed Delay Percent support
+ * Moved the sclock() function from ivm_core.c to hardware.c
+ *********************************************************************************/
+#include "vmopcode.h"
+#include
+#include
+#include //for open()
+#include //for close()
+#include
+#include
+#include
+
+/********************************************************************************
+* Declaration of global variables
+*
+*********************************************************************************/
+static int devmem_c2, devmem_c5;
+static void *portC2, *portC5;
+
+/**
+ * NOTE: Using only core GPIO here
+ * FIXME: This should move to config section and support both CORE and SUS region.
+ */
+
+// unsigned long g_siIspPins = 0x00000000; /*Keeper of JTAG pin state*/
+unsigned short g_usCpu_Frequency = CPU_FREQ_MH_CONFIG; /*Enter your CPU frequency here, unit in MHz.*/
+
+/*********************************************************************************
+* This is the definition of the bit locations of each respective
+* signal in the global variable g_siIspPins.
+*
+* NOTE: Users must add their own implementation here to define
+* the bit location of the signal to target their hardware.
+* The example below is for the Lattice download cable on
+* on the parallel port.
+*
+*********************************************************************************/
+
+
+unsigned long g_ucPinTDI = GPIO_TDI_CONFIG; /* Pin nummber of TDI */
+unsigned long g_ucPinTCK = GPIO_TCK_CONFIG; /* Pin nummber of TCK */
+unsigned long g_ucPinTMS = GPIO_TMS_CONFIG; /* Pin nummber of TMS */
+unsigned long g_ucPinENABLE = GPIO_ENABLE_CONFIG; /* Pin nummber of ENABLE */
+unsigned long g_ucPinTRST = GPIO_TRST_CONFIG; /* Pin nummber of TRST */
+unsigned long g_ucPinTDO = GPIO_TDO_CONFIG; /* Pin nummber of TDO */
+unsigned long g_ucInPort = GP_LVL; /* All TCI,TDO,TMS,TCK are on same register */
+unsigned long g_ucOutPort = GP_LVL; /* All TCI,TDO,TMS,TCK are on same register */
+
+/* For Denverton CPU */
+// const unsigned long g_ucPinTDI = DNV_GPIO_TDI_CONFIG;
+// const unsigned long g_ucPinTCK = DNV_GPIO_TCK_CONFIG;
+// const unsigned long g_ucPinTMS = DNV_GPIO_TMS_CONFIG;
+// const unsigned long g_ucPinTDO = DNV_GPIO_TDO_CONFIG;
+
+/***************************************************************
+*
+* Functions declared in hardware.c module.
+*
+***************************************************************/
+void writePort( unsigned long a_ucPins, unsigned char a_ucValue );
+unsigned char readPort();
+void sclock();
+void ispVMDelay( unsigned short a_usTimeDelay );
+void calibration(void);
+
+/********************************************************************************
+* writePort
+* To apply the specified value to the pins indicated. This routine will
+* be modified for specific systems.
+* As an example, this code uses the IBM-PC standard Parallel port, along with the
+* schematic shown in Lattice documentation, to apply the signals to the
+* JTAG pins.
+*
+* PC Parallel port pin Signal name Port bit address
+* 2 g_ucPinTDI 1
+* 3 g_ucPinTCK 2
+* 4 g_ucPinTMS 4
+* 5 g_ucPinENABLE 8
+* 6 g_ucPinTRST 16
+* 10 g_ucPinTDO 64
+*
+* Parameters:
+* - a_ucPins, which is actually a set of bit flags (defined above)
+* that correspond to the bits of the data port. Each of the I/O port
+* bits that drives an isp programming pin is assigned a flag
+* (through a #define) corresponding to the signal it drives. To
+* change the value of more than one pin at once, the flags are added
+* together, much like file access flags are.
+*
+* The bit flags are only set if the pin is to be changed. Bits that
+* do not have their flags set do not have their levels changed. The
+* state of the port is always manintained in the static global
+* variable g_siIspPins, so that each pin can be addressed individually
+* without disturbing the others.
+*
+* - a_ucValue, which is either HIGH (0x01 ) or LOW (0x00 ). Only these two
+* values are valid. Any non-zero number sets the pin(s) high.
+*
+*********************************************************************************/
+
+void writePort( unsigned long a_ucPins, unsigned char a_ucValue )
+{
+
+ unsigned long siIspPins = 0;
+
+ /* For Denverton */
+ // isp_dnv_gpio_write(a_ucPins, (unsigned int) a_ucValue);
+
+ /* TODO: Convert to bit read/write function */
+ siIspPins = inl_p( g_ucOutPort );
+ if( a_ucValue ){
+ siIspPins |= (1U << a_ucPins);
+ }else{
+ siIspPins &= ~(1U << a_ucPins);
+ }
+ outl_p(siIspPins, g_ucOutPort);
+}
+
+/*********************************************************************************
+*
+* readPort
+*
+* Returns the value of the TDO from the device.
+*
+**********************************************************************************/
+unsigned char readPort()
+{
+ unsigned char ucRet = 0;
+
+ /* For Denverton */
+ // if ( isp_dnv_gpio_read(DNV_GPIO_TDO_CONFIG) ) {
+ // ucRet = 0x01;
+ // }
+ // else {
+ // ucRet = 0x00;
+ // }
+
+ /* TODO: Convert to bit read/write function */
+ if ( inl_p( g_ucInPort ) & (1U << g_ucPinTDO)) {
+ ucRet = 0x01;
+ }
+ else {
+ ucRet = 0x00;
+ }
+ return ( ucRet );
+}
+
+/*********************************************************************************
+* sclock
+*
+* Apply a pulse to TCK.
+*
+* This function is located here so that users can modify to slow down TCK if
+* it is too fast (> 25MHZ). Users can change the IdleTime assignment from 0 to
+* 1, 2... to effectively slowing down TCK by half, quarter...
+*
+*********************************************************************************/
+void sclock()
+{
+ unsigned short IdleTime = 0; //change to > 0 if need to slow down TCK
+ unsigned short usIdleIndex = 0;
+ IdleTime++;
+ for ( usIdleIndex = 0; usIdleIndex < IdleTime; usIdleIndex++ ) {
+ writePort( g_ucPinTCK, 0x01 );
+ }
+ for ( usIdleIndex = 0; usIdleIndex < IdleTime; usIdleIndex++ ) {
+ writePort( g_ucPinTCK, 0x00 );
+ }
+}
+/********************************************************************************
+*
+* ispVMDelay
+*
+*
+* Users must implement a delay to observe a_usTimeDelay, where
+* bit 15 of the a_usTimeDelay defines the unit.
+* 1 = milliseconds
+* 0 = microseconds
+* Example:
+* a_usTimeDelay = 0x0001 = 1 microsecond delay.
+* a_usTimeDelay = 0x8001 = 1 millisecond delay.
+*
+* This subroutine is called upon to provide a delay from 1 millisecond to a few
+* hundreds milliseconds each time.
+* It is understood that due to a_usTimeDelay is defined as unsigned short, a 16 bits
+* integer, this function is restricted to produce a delay to 64000 micro-seconds
+* or 32000 milli-second maximum. The VME file will never pass on to this function
+* a delay time > those maximum number. If it needs more than those maximum, the VME
+* file will launch the delay function several times to realize a larger delay time
+* cummulatively.
+* It is perfectly alright to provide a longer delay than required. It is not
+* acceptable if the delay is shorter.
+*
+* Delay function example--using the machine clock signal of the native CPU------
+* When porting ispVME to a native CPU environment, the speed of CPU or
+* the system clock that drives the CPU is usually known.
+* The speed or the time it takes for the native CPU to execute one for loop
+* then can be calculated as follows:
+* The for loop usually is compiled into the ASSEMBLY code as shown below:
+* LOOP: DEC RA;
+* JNZ LOOP;
+* If each line of assembly code needs 4 machine cycles to execute,
+* the total number of machine cycles to execute the loop is 2 x 4 = 8.
+* Usually system clock = machine clock (the internal CPU clock).
+* Note: Some CPU has a clock multiplier to double the system clock for
+ the machine clock.
+*
+* Let the machine clock frequency of the CPU be F, or 1 machine cycle = 1/F.
+* The time it takes to execute one for loop = (1/F ) x 8.
+* Or one micro-second = F(MHz)/8;
+*
+* Example: The CPU internal clock is set to 100Mhz, then one micro-second = 100/8 = 12
+*
+* The C code shown below can be used to create the milli-second accuracy.
+* Users only need to enter the speed of the cpu.
+*
+**********************************************************************************/
+void ispVMDelay( unsigned short a_usTimeDelay )
+{
+ unsigned short loop_index = 0;
+ unsigned short ms_index = 0;
+ unsigned short us_index = 0;
+
+ if ( a_usTimeDelay & 0x8000 ) /*Test for unit*/
+ {
+ a_usTimeDelay &= ~0x8000; /*unit in milliseconds*/
+ }
+ else { /*unit in microseconds*/
+ a_usTimeDelay = (unsigned short) (a_usTimeDelay/1000); /*convert to milliseconds*/
+ if ( a_usTimeDelay <= 0 ) {
+ a_usTimeDelay = 1; /*delay is 1 millisecond minimum*/
+ }
+ }
+ /*Users can replace the following section of code by their own*/
+ for( ms_index = 0; ms_index < a_usTimeDelay; ms_index++)
+ {
+ /*Loop 1000 times to produce the milliseconds delay*/
+ for (us_index = 0; us_index < 1000; us_index++)
+ { /*each loop should delay for 1 microsecond or more.*/
+ loop_index = 0;
+ do {
+ /*The NOP fakes the optimizer out so that it doesn't toss out the loop code entirely*/
+ asm("nop");
+ }while (loop_index++ < ((g_usCpu_Frequency/8)+(+ ((g_usCpu_Frequency % 8) ? 1 : 0))));/*use do loop to force at least one loop*/
+ }
+ }
+}
+
+/*********************************************************************************
+*
+* calibration
+*
+* It is important to confirm if the delay function is indeed providing
+* the accuracy required. Also one other important parameter needed
+* checking is the clock frequency.
+* Calibration will help to determine the system clock frequency
+* and the loop_per_micro value for one micro-second delay of the target
+* specific hardware.
+*
+**********************************************************************************/
+void calibration(void)
+{
+ /*Apply 2 pulses to TCK.*/
+ writePort( g_ucPinTCK, 0x00 );
+ writePort( g_ucPinTCK, 0x01 );
+ writePort( g_ucPinTCK, 0x00 );
+ writePort( g_ucPinTCK, 0x01 );
+ writePort( g_ucPinTCK, 0x00 );
+
+ /*Delay for 1 millisecond. Pass on 1000 or 0x8001 both = 1ms delay.*/
+ ispVMDelay(0x8001);
+
+ /*Apply 2 pulses to TCK*/
+ writePort( g_ucPinTCK, 0x01 );
+ writePort( g_ucPinTCK, 0x00 );
+ writePort( g_ucPinTCK, 0x01 );
+ writePort( g_ucPinTCK, 0x00 );
+
+ ispVMDelay(0x8001);
+}
+
+void port_test(void)
+{
+ int siRetCode;
+ unsigned char cbit;
+
+ printf("TDI set HIGH.\n");
+ if(scanf("%d",&siRetCode)){}
+ writePort( g_ucPinTDI, 0x01);
+ printf("TDI set LOW.\n");
+ if(scanf("%d",&siRetCode)){}
+ writePort( g_ucPinTDI, 0x00);
+ printf("TMS set HIGH.\n");
+ if(scanf("%d",&siRetCode)){}
+ writePort(g_ucPinTMS, 0x01);
+ printf("TMS set LOW.\n");
+ if(scanf("%d",&siRetCode)){}
+ writePort(g_ucPinTMS, 0x00);
+ printf("TCK set HIGH.\n");
+ if(scanf("%d",&siRetCode)){}
+ writePort(g_ucPinTCK, 0x01);
+ printf("TCK set LOW.\n");
+ if(scanf("%d",&siRetCode)){}
+ writePort(g_ucPinTCK, 0x00);
+ printf("write finished.read begin:\n");
+ if(scanf("%d",&siRetCode)){}
+ cbit = readPort();
+ printf("Read date is %d\n", cbit);
+ printf("read begin:\n");
+ if(scanf("%d",&siRetCode)){}
+ cbit = readPort();
+ printf("Read date is %d\n", cbit);
+ printf("read finished.\n");
+ if(scanf("%d",&siRetCode)){}
+}
+
+
+void isp_dnv_gpio_config(unsigned int gpio, unsigned int dir)
+{
+ volatile unsigned int *buffer;
+ // Select community
+ if(GET_PORT(gpio) == 0xC5){
+ buffer = (volatile unsigned int *)(portC5 + OFFSET_ADDR(gpio));
+ }else{
+ buffer = (volatile unsigned int *)(portC2 + OFFSET_ADDR(gpio));
+ }
+ // set mode to GPIO, set pin direction.
+ *buffer &= (~((unsigned int)7)) << 10; // clear [12:10]
+ *buffer &= (~((unsigned int)3)) << 8; // clear [9:8]
+ *buffer |= ((unsigned int)dir & 0x3) << 8; // set [9:8]
+}
+
+void isp_dnv_gpio_write(unsigned int gpio, unsigned int value)
+{
+ volatile unsigned char *buffer;
+ // Select community
+ if(GET_PORT(gpio) == 0xC5){
+ buffer = (volatile unsigned char *)(portC5 + OFFSET_ADDR(gpio));
+ }else{
+ buffer = (volatile unsigned char *)(portC2 + OFFSET_ADDR(gpio));
+ }
+ if(value) {
+ *buffer = DNV_GPIO_LVL_HIGH;
+ } else {
+ *buffer = DNV_GPIO_LVL_LOW;
+ }
+}
+
+int isp_dnv_gpio_read(unsigned int gpio)
+{
+ volatile unsigned int *buffer;
+ // Select community
+ if(GET_PORT(gpio) == 0xC5){
+ buffer = (volatile unsigned int *)(portC5 + OFFSET_ADDR(gpio));
+ }else{
+ buffer = (volatile unsigned int *)(portC2 + OFFSET_ADDR(gpio));
+ }
+ return (int)((*buffer & 0x2) >> 1);
+}
+
+
+void isp_dnv_gpio_init(void){
+
+ devmem_c2 = open("/dev/mem", O_RDWR | O_SYNC);
+ if (devmem_c2 == -1){
+ perror("Can't open /dev/mem.");
+ return;
+ }
+
+ devmem_c5 = open("/dev/mem", O_RDWR | O_SYNC);
+ if (devmem_c5 == -1){
+ perror("Can't open /dev/mem.");
+ return;
+ }
+
+ portC2 = mmap(NULL, MAP_SIZE(g_ucPinTCK) , PROT_READ | PROT_WRITE, MAP_SHARED, devmem_c2, g_ucPinTCK & ~MAP_MASK);
+ if (portC2 == MAP_FAILED) {
+ perror("Can't map memory: ");
+ return;
+ }
+ portC5 = mmap(NULL, MAP_SIZE(g_ucPinTDO) , PROT_READ | PROT_WRITE, MAP_SHARED, devmem_c5, g_ucPinTDO & ~MAP_MASK);
+ if (portC2 == MAP_FAILED) {
+ perror("Can't map memory: ");
+ return;
+ }
+}
+
+void isp_dnv_gpio_deinit(void){
+ munmap(portC2, MAP_SIZE(g_ucPinTCK));
+ munmap(portC5, MAP_SIZE(g_ucPinTDO));
+ close(devmem_c2);
+ close(devmem_c5);
+}
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/ispvm b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/ispvm
new file mode 100755
index 000000000000..202103900f69
Binary files /dev/null and b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/ispvm differ
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/ispvm_ui.c b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/ispvm_ui.c
new file mode 100644
index 000000000000..6180007d74d0
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/ispvm_ui.c
@@ -0,0 +1,1043 @@
+/**************************************************************
+*
+* Lattice Semiconductor Corp. Copyright 2008
+*
+* ispVME Embedded allows programming of Lattice's suite of FPGA
+* devices on embedded systems through the JTAG port. The software
+* is distributed in source code form and is open to re - distribution
+* and modification where applicable.
+*
+* ispVME Embedded C Source comprised with 3 modules:
+* ispvm_ui.c is the module provides input and output support.
+* ivm_core.c is the module interpret the VME file(s).
+* hardware.c is the module access the JTAG port of the device(s).
+*
+* The optional module cable.c is for supporting Lattice's parallel
+* port ispDOWNLOAD cable on DOS and Windows 95/98 O/S. It can be
+* requested from Lattice's ispVMSupport.
+*
+***************************************************************/
+
+
+/**************************************************************
+*
+* Revision History of ispvm_ui.c
+*
+* 3/6/07 ht Added functions vme_out_char(),vme_out_hex(),
+* vme_out_string() to provide output resources.
+* Consolidate all printf() calls into the added output
+* functions.
+*
+* 09/11/07 NN Added Global variables initialization
+* 09/24/07 NN Added a switch allowing users to do calibration.
+* Calibration will help to determine the system clock frequency
+* and the count value for one micro-second delay of the target
+* specific hardware.
+* Removed Delay Percent support
+* 11/15/07 NN moved the checking of the File CRC to the end of processing
+* 08/28/08 NN Added Calculate checksum support.
+***************************************************************/
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "vmopcode.h"
+
+/***************************************************************
+*
+* File pointer to the VME file.
+*
+***************************************************************/
+
+FILE * g_pVMEFile = NULL;
+
+#define VME_DEBUG
+
+#define DEBUG
+#ifdef DEBUG
+#define Debug_printf(fmt, args...) printf(fmt, ##args);
+#else
+#define Debug_printf(fmt, args...)
+#endif
+
+/***************************************************************
+*
+* Functions declared in this ispvm_ui.c module
+*
+***************************************************************/
+unsigned char GetByte(void);
+void vme_out_char(unsigned char charOut);
+void vme_out_hex(unsigned char hexOut);
+void vme_out_string(char *stringOut);
+void ispVMMemManager( signed char cTarget, unsigned short usSize );
+void ispVMFreeMem(void);
+void error_handler( short a_siRetCode, char * pszMessage );
+signed char ispVM( const char * a_pszFilename );
+long isp_vme_file_size_get(void);
+int isp_vme_file_size_set(char *file_name);
+int isp_print_progess_bar(long pec);
+void print_usage(char *app_name);
+/***************************************************************
+*
+* Global variables.
+*
+***************************************************************/
+unsigned short g_usPreviousSize = 0;
+unsigned short g_usExpectedCRC = 0;
+static unsigned long vme_file_size = 0;
+
+/***************************************************************
+*
+* External variables and functions declared in ivm_core.c module.
+*
+***************************************************************/
+extern signed char ispVMCode();
+extern void ispVMCalculateCRC32( unsigned char a_ucData );
+extern void ispVMStart();
+extern void ispVMEnd();
+extern unsigned short g_usCalculatedCRC;
+extern unsigned short g_usDataType;
+extern unsigned char * g_pucOutMaskData,
+ * g_pucInData,
+ * g_pucOutData,
+ * g_pucHIRData,
+ * g_pucTIRData,
+ * g_pucHDRData,
+ * g_pucTDRData,
+ * g_pucOutDMaskData,
+ * g_pucIntelBuffer;
+extern unsigned char * g_pucHeapMemory;
+extern unsigned short g_iHeapCounter;
+extern unsigned short g_iHEAPSize;
+extern unsigned short g_usIntelDataIndex;
+extern unsigned short g_usIntelBufferSize;
+extern LVDSPair * g_pLVDSList;
+//08/28/08 NN Added Calculate checksum support.
+extern unsigned long g_usChecksum;
+extern unsigned int g_uiChecksumIndex;
+/***************************************************************
+*
+* External variables and functions declared in hardware.c module.
+*
+***************************************************************/
+extern void calibration(void);
+extern void writePort( unsigned long a_ucPins, unsigned char a_ucValue );
+extern unsigned short g_usCpu_Frequency;
+extern unsigned long g_ucInPort;
+extern unsigned long g_ucOutPort;
+
+#define SYS_CMD_LEN (100)
+#define PCA9536_INPUT_REG (0)
+#define PCA9536_OUTPUT_REG (1)
+#define PCA9536_POL_INV_REG (2)
+#define PCA9536_CFG_REG (3)
+#define PCA9536_I2C_BUS (0)
+#define PCA9536_I2C_ADDR (0x41)
+enum cel_error{
+CEL_NO_ERR = 0,
+CEL_ERR_INVALID_DATA,
+};
+enum IOx_index {
+CPLD_BB_INDEX = 0,
+CPLD_CB_INDEX,
+CPLD_FCB_INDEX,
+CPLD_SWB_INDEX,
+CPLD_TOTAL_NUM,
+
+};
+char IOx_map[] = {
+1,//IOx index of pca9536 corresponding to CPLD_BB
+2,//IOx index of pca9536 corresponding to CPLD_CB
+0,//IOx index of pca9536 corresponding to CPLD_FCB
+3,//IOx index of pca9536 corresponding to CPLD_SWB
+};
+/***************************************************************
+*
+* Supported VME versions.
+*
+***************************************************************/
+
+const char * const g_szSupportedVersions[] = { "__VME2.0", "__VME3.0", "____12.0", "____12.1", 0 };
+
+
+/***************************************************************
+*
+* GetByte
+*
+* Returns a byte to the caller. The returned byte depends on the
+* g_usDataType register. If the HEAP_IN bit is set, then the byte
+* is returned from the HEAP. If the LHEAP_IN bit is set, then
+* the byte is returned from the intelligent buffer. Otherwise,
+* the byte is returned directly from the VME file.
+*
+***************************************************************/
+
+unsigned char GetByte()
+{
+ unsigned char ucData = 0;
+ /* Prepare progress bar calculation */
+ static long offset = 0;
+ int pec = 0;
+ long file_size = isp_vme_file_size_get();
+ int bytes_pec = (file_size + 99) / 100;
+
+ if ( g_usDataType & HEAP_IN ) {
+
+ /***************************************************************
+ *
+ * Get data from repeat buffer.
+ *
+ ***************************************************************/
+
+ if ( g_iHeapCounter > g_iHEAPSize ) {
+
+ /***************************************************************
+ *
+ * Data over-run.
+ *
+ ***************************************************************/
+
+ return 0xFF;
+ }
+
+ ucData = g_pucHeapMemory[ g_iHeapCounter++ ];
+ }
+ else if ( g_usDataType & LHEAP_IN ) {
+
+ /***************************************************************
+ *
+ * Get data from intel buffer.
+ *
+ ***************************************************************/
+
+ if ( g_usIntelDataIndex >= g_usIntelBufferSize ) {
+
+ /***************************************************************
+ *
+ * Data over-run.
+ *
+ ***************************************************************/
+
+ return 0xFF;
+ }
+
+ ucData = g_pucIntelBuffer[ g_usIntelDataIndex++ ];
+ }
+ else {
+
+ /***************************************************************
+ *
+ * Get data from file.
+ *
+ ***************************************************************/
+
+ ucData = (unsigned char)fgetc( g_pVMEFile );
+ /* Update the progress bar */
+ pec = ++offset / bytes_pec;
+ if(offset <= (pec * bytes_pec))
+ isp_print_progess_bar(pec);
+ else if(offset >= (file_size - 2))
+ isp_print_progess_bar(100);
+ if ( feof( g_pVMEFile ) ) {
+
+ /***************************************************************
+ *
+ * Reached EOF.
+ *
+ ***************************************************************/
+
+ return 0xFF;
+ }
+ /***************************************************************
+ *
+ * Calculate the 32-bit CRC if the expected CRC exist.
+ *
+ ***************************************************************/
+ if( g_usExpectedCRC != 0)
+ {
+ ispVMCalculateCRC32(ucData);
+ }
+ }
+
+ return ( ucData );
+}
+
+/***************************************************************
+*
+* vme_out_char
+*
+* Send a character out to the output resource if available.
+* The monitor is the default output resource.
+*
+*
+***************************************************************/
+void vme_out_char(unsigned char charOut)
+{
+ printf("%c",charOut);
+}
+/***************************************************************
+*
+* vme_out_hex
+*
+* Send a character out as in hex format to the output resource
+* if available. The monitor is the default output resource.
+*
+*
+***************************************************************/
+void vme_out_hex(unsigned char hexOut)
+{
+ printf("%.2X",hexOut);
+}
+/***************************************************************
+*
+* vme_out_string
+*
+* Send a text string out to the output resource if available.
+* The monitor is the default output resource.
+*
+*
+***************************************************************/
+void vme_out_string(char *stringOut)
+{
+ if(stringOut)
+ {
+ printf("%s",stringOut);
+ }
+
+}
+/***************************************************************
+*
+* ispVMMemManager
+*
+* Allocate memory based on cTarget. The memory size is specified
+* by usSize.
+*
+***************************************************************/
+
+void ispVMMemManager( signed char cTarget, unsigned short usSize )
+{
+ switch ( cTarget ) {
+ case XTDI:
+ case TDI:
+ if ( g_pucInData != NULL ) {
+ if ( g_usPreviousSize == usSize ) {/*memory exist*/
+ break;
+ }
+ else {
+ free( g_pucInData );
+ g_pucInData = NULL;
+ }
+ }
+ g_pucInData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ g_usPreviousSize = usSize;
+ /* FALLTHRU */
+ case XTDO:
+ case TDO:
+ if ( g_pucOutData!= NULL ) {
+ if ( g_usPreviousSize == usSize ) { /*already exist*/
+ break;
+ }
+ else {
+ free( g_pucOutData );
+ g_pucOutData = NULL;
+ }
+ }
+ g_pucOutData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ g_usPreviousSize = usSize;
+ break;
+ case MASK:
+ if ( g_pucOutMaskData != NULL ) {
+ if ( g_usPreviousSize == usSize ) {/*already allocated*/
+ break;
+ }
+ else {
+ free( g_pucOutMaskData );
+ g_pucOutMaskData = NULL;
+ }
+ }
+ g_pucOutMaskData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ g_usPreviousSize = usSize;
+ break;
+ case HIR:
+ if ( g_pucHIRData != NULL ) {
+ free( g_pucHIRData );
+ g_pucHIRData = NULL;
+ }
+ g_pucHIRData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ break;
+ case TIR:
+ if ( g_pucTIRData != NULL ) {
+ free( g_pucTIRData );
+ g_pucTIRData = NULL;
+ }
+ g_pucTIRData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ break;
+ case HDR:
+ if ( g_pucHDRData != NULL ) {
+ free( g_pucHDRData );
+ g_pucHDRData = NULL;
+ }
+ g_pucHDRData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ break;
+ case TDR:
+ if ( g_pucTDRData != NULL ) {
+ free( g_pucTDRData );
+ g_pucTDRData = NULL;
+ }
+ g_pucTDRData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ break;
+ case HEAP:
+ if ( g_pucHeapMemory != NULL ) {
+ free( g_pucHeapMemory );
+ g_pucHeapMemory = NULL;
+ }
+ g_pucHeapMemory = ( unsigned char * ) malloc( usSize + 2 );
+ break;
+ case DMASK:
+ if ( g_pucOutDMaskData != NULL ) {
+ if ( g_usPreviousSize == usSize ) { /*already allocated*/
+ break;
+ }
+ else {
+ free( g_pucOutDMaskData );
+ g_pucOutDMaskData = NULL;
+ }
+ }
+ g_pucOutDMaskData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ g_usPreviousSize = usSize;
+ break;
+ case LHEAP:
+ if ( g_pucIntelBuffer != NULL ) {
+ free( g_pucIntelBuffer );
+ g_pucIntelBuffer = NULL;
+ }
+ g_pucIntelBuffer = ( unsigned char * ) malloc( usSize + 2 );
+ break;
+ case LVDS:
+ if ( g_pLVDSList != NULL ) {
+ free( g_pLVDSList );
+ g_pLVDSList = NULL;
+ }
+ g_pLVDSList = ( LVDSPair * ) calloc( usSize, sizeof( LVDSPair ) );
+ break;
+ default:
+ return;
+ }
+}
+
+/***************************************************************
+*
+* ispVMFreeMem
+*
+* Free memory that were dynamically allocated.
+*
+***************************************************************/
+
+void ispVMFreeMem()
+{
+ if ( g_pucHeapMemory != NULL ) {
+ free( g_pucHeapMemory );
+ g_pucHeapMemory = NULL;
+ }
+
+ if ( g_pucOutMaskData != NULL ) {
+ free( g_pucOutMaskData );
+ g_pucOutMaskData = NULL;
+ }
+
+ if ( g_pucInData != NULL ) {
+ free( g_pucInData );
+ g_pucInData = NULL;
+ }
+
+ if ( g_pucOutData != NULL ) {
+ free( g_pucOutData );
+ g_pucOutData = NULL;
+ }
+
+ if ( g_pucHIRData != NULL ) {
+ free( g_pucHIRData );
+ g_pucHIRData = NULL;
+ }
+
+ if ( g_pucTIRData != NULL ) {
+ free( g_pucTIRData );
+ g_pucTIRData = NULL;
+ }
+
+ if ( g_pucHDRData != NULL ) {
+ free( g_pucHDRData );
+ g_pucHDRData = NULL;
+ }
+
+ if ( g_pucTDRData != NULL ) {
+ free( g_pucTDRData );
+ g_pucTDRData = NULL;
+ }
+
+ if ( g_pucOutDMaskData != NULL ) {
+ free( g_pucOutDMaskData );
+ g_pucOutDMaskData = NULL;
+ }
+
+ if ( g_pucIntelBuffer != NULL ) {
+ free( g_pucIntelBuffer );
+ g_pucIntelBuffer = NULL;
+ }
+
+ if ( g_pLVDSList != NULL ) {
+ free( g_pLVDSList );
+ g_pLVDSList = NULL;
+ }
+}
+
+/***************************************************************
+*
+* error_handler
+*
+* Reports the error message.
+*
+***************************************************************/
+
+void error_handler( short a_siRetCode, char * pszMessage )
+{
+ const char * pszErrorMessage[] = { "pass",
+ "verification fail",
+ "can't find the file",
+ "wrong file type",
+ "file error",
+ "option error",
+ "crc verification error" };
+
+ strcpy( pszMessage, pszErrorMessage[ -a_siRetCode ] );
+}
+/***************************************************************
+*
+* ispVM
+*
+* The entry point of the ispVM embedded. If the version and CRC
+* are verified, then the VME will be processed.
+*
+***************************************************************/
+
+signed char ispVM( const char * a_pszFilename )
+{
+ char szFileVersion[ 9 ] = { 0 };
+ signed char cRetCode = 0;
+ signed char cIndex = 0;
+ signed char cVersionIndex = 0;
+ unsigned char ucReadByte = 0;
+
+ /***************************************************************
+ *
+ * Global variables initialization.
+ *
+ * 09/11/07 NN Added
+ ***************************************************************/
+ g_pucHeapMemory = NULL;
+ g_iHeapCounter = 0;
+ g_iHEAPSize = 0;
+ g_usIntelDataIndex = 0;
+ g_usIntelBufferSize = 0;
+ g_usPreviousSize = 0;
+
+ /***************************************************************
+ *
+ * Open a file pointer to the VME file.
+ *
+ ***************************************************************/
+
+ if ( ( g_pVMEFile = fopen( a_pszFilename, "rb" ) ) == NULL ) {
+ return VME_FILE_READ_FAILURE;
+ }
+ g_usCalculatedCRC = 0;
+ g_usExpectedCRC = 0;
+ ucReadByte = GetByte();
+ switch( ucReadByte ) {
+ case FILE_CRC:
+
+ /***************************************************************
+ *
+ * Read and store the expected CRC to do the comparison at the end.
+ * Only versions 3.0 and higher support CRC protection.
+ *
+ ***************************************************************/
+
+ g_usExpectedCRC = (unsigned char ) fgetc( g_pVMEFile );
+ g_usExpectedCRC <<= 8;
+ g_usExpectedCRC |= fgetc( g_pVMEFile );
+
+
+ /***************************************************************
+ *
+ * Read and store the version of the VME file.
+ *
+ ***************************************************************/
+
+ for ( cIndex = 0; cIndex < 8; cIndex++ ) {
+ szFileVersion[ cIndex ] = GetByte();
+ }
+
+ break;
+ default:
+
+ /***************************************************************
+ *
+ * Read and store the version of the VME file. Must be version 2.0.
+ *
+ ***************************************************************/
+
+ szFileVersion[ 0 ] = ( signed char ) ucReadByte;
+ for ( cIndex = 1; cIndex < 8; cIndex++ ) {
+ szFileVersion[ cIndex ] = GetByte();
+ }
+
+ break;
+ }
+
+ /***************************************************************
+ *
+ * Compare the VME file version against the supported version.
+ *
+ ***************************************************************/
+ for ( cVersionIndex = 0; g_szSupportedVersions[ cVersionIndex ] != 0; cVersionIndex++ ) {
+ for ( cIndex = 0; cIndex < 8; cIndex++ ) {
+ if ( szFileVersion[ cIndex ] != g_szSupportedVersions[ cVersionIndex ][ cIndex ] ) {
+ cRetCode = VME_VERSION_FAILURE;
+ break;
+ }
+ cRetCode = 0;
+ }
+
+ if ( cRetCode == 0 ) {
+
+ /***************************************************************
+ *
+ * Found matching version, break.
+ *
+ ***************************************************************/
+
+ break;
+ }
+ }
+
+ if ( cRetCode < 0 ) {
+
+ /***************************************************************
+ *
+ * VME file version failed to match the supported versions.
+ *
+ ***************************************************************/
+
+ fclose( g_pVMEFile );
+ g_pVMEFile = NULL;
+ return VME_VERSION_FAILURE;
+ }
+
+ /***************************************************************
+ *
+ * Enable the JTAG port to communicate with the device.
+ * Set the JTAG state machine to the Test-Logic/Reset State.
+ *
+ ***************************************************************/
+
+ ispVMStart();
+
+ /***************************************************************
+ *
+ * Process the VME file.
+ *
+ ***************************************************************/
+
+ cRetCode = ispVMCode();
+
+ /***************************************************************
+ *
+ * Set the JTAG State Machine to Test-Logic/Reset state then disable
+ * the communication with the JTAG port.
+ *
+ ***************************************************************/
+
+ ispVMEnd();
+
+ fclose( g_pVMEFile );
+ g_pVMEFile = NULL;
+
+
+ ispVMFreeMem();
+
+ /***************************************************************
+ *
+ * Compare the expected CRC versus the calculated CRC.
+ *
+ ***************************************************************/
+
+ if ( cRetCode == 0 && g_usExpectedCRC != 0 && ( g_usExpectedCRC != g_usCalculatedCRC ) ) {
+ printf( "Expected CRC: 0x%.4X\n", g_usExpectedCRC );
+ printf( "Calculated CRC: 0x%.4X\n", g_usCalculatedCRC );
+ return VME_CRC_FAILURE;
+ }
+
+ return ( cRetCode );
+}
+
+// inline char *strlwr(char *str)
+// {
+// char *orig = str;
+
+// for (; *str != '\0'; str++)
+// *str = tolower(*str);
+
+// return orig;
+// }
+
+int isp_vme_file_size_set(char *file_name)
+{
+ struct stat statbuf;
+
+ stat(file_name, &statbuf);
+ vme_file_size = statbuf.st_size;
+
+ return 0;
+}
+
+long isp_vme_file_size_get(void)
+{
+ return vme_file_size;
+}
+
+int isp_print_progess_bar(long pec)
+{
+ int i = 0;
+
+ printf("[");
+ for(i = 0; i < (pec / 2); i++) {
+ printf("=");
+ }
+ for(i = pec / 2; i < 50; i++) {
+ printf(" ");
+ }
+ printf("]");
+ printf(" [%ld%%]\r", pec);
+ fflush(stdout);
+ if(pec == 100)
+ printf("\n");
+
+ return 0;
+}
+
+void print_usage(char *app_name){
+ printf(" usage: %s [options] [filename]\n", app_name);
+ printf(" Options:\n");
+ printf(" -h : to print this message.\n");
+ printf(" -c : to select the JTAG chain 0,1,2\n");
+ printf(" default is at 0.\n");
+ printf(" -f : to specify CPU clock frequency in MHz.\n");
+ printf(" -i : set output channel of pca9536, range:\n");
+ printf(" 0 - CPLD_BB \n");
+ printf(" 1 - CPLD_CB \n");
+ printf(" 2 - CPLD_FCB \n");
+ printf(" 3 - CPLD_SWB \n");
+}
+
+/*Description: execute a system command contained in a string
+*param_in: tmp - system command string
+*param_out: NONE
+*ret_val: 0 - on successful
+* 1 - on failed
+*/
+int exec_cmd (char * tmp)
+{
+ int status;
+ status = system(tmp);
+ if (-1 ==status){
+ return CEL_ERR_INVALID_DATA;
+ }else{
+ if (WIFEXITED(status)){
+ if (0 == WEXITSTATUS(status)){
+ return CEL_NO_ERR;
+ }else{
+ return CEL_ERR_INVALID_DATA;
+ }
+ }else{
+ return CEL_ERR_INVALID_DATA;
+ }
+ }
+ return CEL_NO_ERR;
+}
+/*Description: set pca9536 IO0~IO3 output level
+*param_in: io_index - index of IO pin
+*param_out:NONE
+*ret_val: 0 - on successful
+* -1 - on failed
+*/
+int set_pca9536_output(int io_index)
+{
+ int sys_cmd_rc = 0;
+ char sys_cmd[SYS_CMD_LEN] = {0};
+ char reg_val = 0xFF & (~(1 << IOx_map[io_index]));
+ printf("set pca9536 IO%d to level 0 \n", IOx_map[io_index]);
+ memset(sys_cmd, 0, SYS_CMD_LEN);
+ sprintf(sys_cmd, "i2cset -y %d 0x%x 0x%x 0x%x", PCA9536_I2C_BUS,
+ PCA9536_I2C_ADDR, PCA9536_OUTPUT_REG, reg_val);
+ sys_cmd_rc = exec_cmd(sys_cmd);
+ if (sys_cmd_rc != 0) {
+ printf("set pca9536 IO%d to level 0 failed!\n", IOx_map[io_index]);
+ return -1;
+ }
+ return sys_cmd_rc;
+}
+
+/***************************************************************
+*
+* main
+*
+***************************************************************/
+int main( int argc, char * argv[] )
+{
+ short siRetCode = 0;
+ short sicalibrate = 1;
+ short setCpuFrequency = 0;
+ /* ChannelIndex: indicate which channel on PCA9536 is selected */
+ int ChannelIndex = -1;
+ char sys_cmd[SYS_CMD_LEN] = {0};
+ int setChannel = 0;
+ int sys_cmd_rc = 0;
+
+ char *cpld_img = "cpld.vme";
+ int JTAG_chain = 0;
+ int option;
+ //08/28/08 NN Added Calculate checksum support.
+ g_usChecksum = 0;
+ g_uiChecksumIndex = 0;
+
+ vme_out_string( " Lattice Semiconductor Corp.\n" );
+ vme_out_string( "\n ispVME(tm) V");
+ vme_out_string( VME_VERSION_NUMBER );
+ vme_out_string(" Copyright 1998-2011.\n");
+ vme_out_string( "\nFor daisy chain programming of all in-system programmable devices\n" );
+ vme_out_string( "\nCLS internal version 1.1.0 for Phalanx, Fishbone48, and Fishbone32.\n\n" );
+
+ while( ( option = getopt(argc, argv, "i:f:c:h")) != -1 ){
+ switch (option){
+ case 'h':
+ print_usage(argv[0]);
+ return 0;
+ case 'c':
+ // set JTAG chain number
+ JTAG_chain = atoi(optarg);
+ break;
+ case 'f':
+ // set CPU frequency
+ g_usCpu_Frequency = atoi(optarg);
+ setCpuFrequency = 1;
+ break;
+ case 'i':
+ ChannelIndex = atoi(optarg);
+ /* printf("channel_index=%d\n", ChannelIndex); */
+ break;
+ case '?':
+ print_usage(argv[0]);
+ return -1;
+ }
+ }
+
+ if( argc - optind )
+ cpld_img = argv[optind];
+
+ if( JTAG_chain < 0 || JTAG_chain > 2 ){
+ //print usage and return error
+ printf("Invalid JTAG chain specify: %d\n", JTAG_chain);
+ print_usage(argv[0]);
+ return -1;
+ }
+
+ if( g_usCpu_Frequency <= 0 && setCpuFrequency ){
+ //print usage and return error
+ printf("Invalid CPU frequency specify: %d\n", g_usCpu_Frequency);
+ print_usage(argv[0]);
+ return -1;
+ }
+
+ if (ChannelIndex != -1) {
+ if (ChannelIndex < 0 || ChannelIndex > 3) {
+ printf("Invalid pca9536 channel index! \n");
+ print_usage(argv[0]);
+ return -1;
+ } else {
+ printf("pca9536 channel index: %d \n", ChannelIndex);
+ setChannel = 1;
+ }
+ } else {
+ printf("pca9536 output channel not set,use default value 0 ! \n");
+ ChannelIndex = 0;
+ setChannel = 1;
+ }
+ /*printf("exit programm 1 \n");
+ * exit(1);
+ */
+ if (iopl(3))
+ {
+ perror("iopl");
+ exit(1);/* reminder here: do not use "return", I warned */
+ }
+ else
+ {
+
+ /* For Denvertion CPU */
+ // isp_dnv_gpio_init();
+ // isp_dnv_gpio_config(GPIO_TCK_CONFIG, GPIO_DIR_OUTPUT);
+ // isp_dnv_gpio_config(GPIO_TMS_CONFIG, GPIO_DIR_OUTPUT);
+ // isp_dnv_gpio_config(GPIO_TDI_CONFIG, GPIO_DIR_OUTPUT);
+ // isp_dnv_gpio_config(GPIO_TDO_CONFIG, GPIO_DIR_INPUT);
+
+
+ /* TODO: Convert to bit read/write function */
+ // Set ICHx GPIO_USE_SEL of TDI,TDO,TMS,TCK,GPIO14
+ unsigned long data = 0;
+ data = inl_p(GPIO_USE_SEL);
+ data |= (1U << GPIO_TCK_CONFIG);
+ data |= (1U << GPIO_TMS_CONFIG);
+ data |= (1U << GPIO_TDI_CONFIG);
+ data |= (1U << GPIO_TDO_CONFIG);
+ data |= (1U << 14);
+ outl_p(data, GPIO_USE_SEL);
+ // Set ICHx GP_IO_SEL of TDI,TDO,TMS,TCK,GPIO14
+ data = inl_p(GP_IO_SEL);
+ data &= ~(1U << GPIO_TCK_CONFIG);
+ data &= ~(1U << GPIO_TMS_CONFIG);
+ data &= ~(1U << GPIO_TDI_CONFIG);
+ data &= ~(1U << 14);
+ data |= (1U << GPIO_TDO_CONFIG);
+ outl_p(data, GP_IO_SEL);
+
+ // Set ICHx GPIO_USE_SEL of GPIO70
+ data = inl_p(GPIO_USE_SEL3);
+ data |= (1U << 6);
+ outl_p(data, GPIO_USE_SEL3);
+ // Set ICHx GP_IO_SEL of GPIO70
+ data = inl_p(GP_IO_SEL3);
+ data &= ~(1U << 6);
+ outl_p(data, GP_IO_SEL3);
+ }
+
+ /* FIXME: export and setting GPIO register bank on the fly could cause a bug.
+ * Plan to add the function to set/clear GPIO register bit for more sucure.
+ */
+ /* Switch to control JTAG chain muxes */
+ switch (JTAG_chain){
+ case 0:
+ printf("Select main JTAG chain\n");
+ // Set GPIO70 to Low
+ g_ucOutPort = GP_LVL3;
+ writePort( 6, 0x00 );
+ break;
+ case 1:
+ printf("Select Top line card JTAG chain\n");
+ // Ste GPIO70 to High
+ g_ucOutPort = GP_LVL3;
+ writePort( 6, 0x01 );
+ // Ste GPIO14 to Low
+ g_ucOutPort = GP_LVL;
+ writePort( 14, 0x00 );
+ break;
+ case 2:
+ printf("Select Buttom line card JTAG chain\n");
+ // Ste GPIO70 to High
+ g_ucOutPort = GP_LVL3;
+ writePort( 6, 0x01 );
+ // Ste GPIO14 to High
+ g_ucOutPort = GP_LVL;
+ writePort( 14, 0x01 );
+ break;
+ }
+
+ /* FIXME: This line is very important for TDI,TMS,TCK,TDO */
+ // Set the register back to first bank!
+ g_ucOutPort = GP_LVL;
+
+ printf("Set CPU frequency to %d MHz\n", g_usCpu_Frequency);
+
+ if (setChannel) {
+ printf("Set pca9536 output channel index to %d \n", ChannelIndex);
+ /* exit(0); */
+ memset(sys_cmd, 0, SYS_CMD_LEN);
+ sprintf(sys_cmd, "sudo su");
+ sys_cmd_rc = exec_cmd(sys_cmd);
+ if (sys_cmd_rc != 0) {
+ printf("sudo su failed!\n");
+ return -1;
+ }
+ memset(sys_cmd, 0, SYS_CMD_LEN);
+ sprintf(sys_cmd, "echo jtag_sel 0x41 > /sys/bus/i2c/devices/i2c-0/new_device");
+ sys_cmd_rc = exec_cmd(sys_cmd);
+ if (sys_cmd_rc != 0) {
+ printf("add pca9536 to i2c-0 failed!\n");
+ return -1;
+ }
+ memset(sys_cmd, 0, SYS_CMD_LEN);
+ sprintf(sys_cmd, "i2cset -y %d 0x%x 0x%x 0xf0", PCA9536_I2C_BUS, PCA9536_I2C_ADDR, PCA9536_CFG_REG);
+ sys_cmd_rc = exec_cmd(sys_cmd);
+ if (sys_cmd_rc != 0) {
+ printf("set pca9536 IO0~IO3 to output mode failed!\n");
+ return -1;
+ }
+ sys_cmd_rc = set_pca9536_output(ChannelIndex);
+ if (sys_cmd_rc != 0) {
+ printf("set pca9536 IO%d output 0 failed!\n", IOx_map[ChannelIndex]);
+ return -1;
+ }
+ }
+
+ siRetCode = 0;
+ if(sicalibrate)
+ {
+ vme_out_string ("calibration ....\n\n");
+ calibration();
+ }
+
+ printf( "Processing virtual machine file (");
+ printf( "%s",cpld_img);
+ printf(")......\n\n");
+ isp_vme_file_size_set(cpld_img);
+ siRetCode = ispVM(cpld_img);
+
+ /* Set JTAG chain muxes to default chain. */
+ // Set GPIO70 to Low
+ g_ucOutPort = GP_LVL3;
+ writePort( 6, 0x00 );
+
+ /* For Denverton CPU */
+ // isp_dnv_gpio_deinit();
+
+ if ( siRetCode < 0 ) {
+ vme_out_string( "Failed due to ");
+ printf( " return code %d\n\n", siRetCode);
+ vme_out_string( "+=======+\n" );
+ vme_out_string( "| FAIL! |\n" );
+ vme_out_string( "+=======+\n\n" );
+ }else {
+ vme_out_string( "+=======+\n" );
+ vme_out_string( "| PASS! |\n" );
+ vme_out_string( "+=======+\n\n" );
+ //08/28/08 NN Added Calculate checksum support.
+ if(g_usChecksum != 0)
+ {
+ g_usChecksum &= 0xFFFF;
+ printf("Data Checksum: %.4lx\n\n",g_usChecksum);
+ g_usChecksum = 0;
+ }
+ }
+
+ if (iopl(0))
+ {
+ perror("iopl");
+ exit(1);/* reminder here: do not use "return", I warned */
+ }
+ exit( siRetCode );
+}
+
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/ivm_core.c b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/ivm_core.c
new file mode 100644
index 000000000000..fd6fa7b987c2
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/ivm_core.c
@@ -0,0 +1,3081 @@
+/***************************************************************
+ *
+ * Lattice Semiconductor Corp. Copyright 2009
+ *
+ * ispVME Embedded allows programming of Lattice's suite of FPGA
+ * devices on embedded systems through the JTAG port. The software
+ * is distributed in source code form and is open to re - distribution
+ * and modification where applicable.
+ *
+ * Revision History of ivm_core.c module:
+ * 4/25/06 ht Change some variables from unsigned short or int
+ * to long int to make the code compiler independent.
+ * 5/24/06 ht Support using RESET (TRST) pin as a special purpose
+ * control pin such as triggering the loading of known
+ * state exit.
+ * 3/6/07 ht added functions to support output to terminals
+ *
+ * 09/24/07 NN Type cast mismatch variables
+ * Moved the sclock() function to hardware.c
+ * 08/28/08 NN Added Calculate checksum support.
+ * 4/1/09 Nguyen replaced the recursive function call codes on
+ * the ispVMLCOUNT function
+ *
+ ***************************************************************/
+
+#include
+#include
+#include "vmopcode.h"
+
+/***************************************************************
+ *
+ * Global variables used to specify the flow control and data type.
+ *
+ * g_usFlowControl: flow control register. Each bit in the
+ * register can potentially change the
+ * personality of the embedded engine.
+ * g_usDataType: holds the data type of the current row.
+ *
+ ***************************************************************/
+
+unsigned short g_usFlowControl = 0x0000;
+unsigned short g_usDataType = 0x0000;
+
+/***************************************************************
+ *
+ * Global variables used to specify the ENDDR and ENDIR.
+ *
+ * g_ucEndDR: the state that the device goes to after SDR.
+ * g_ucEndIR: the state that the device goes to after SIR.
+ *
+ ***************************************************************/
+
+unsigned char g_ucEndDR = DRPAUSE;
+unsigned char g_ucEndIR = IRPAUSE;
+
+/***************************************************************
+ *
+ * Global variables used to support header/trailer.
+ *
+ * g_usHeadDR: the number of lead devices in bypass.
+ * g_usHeadIR: the sum of IR length of lead devices.
+ * g_usTailDR: the number of tail devices in bypass.
+ * g_usTailIR: the sum of IR length of tail devices.
+ *
+ ***************************************************************/
+
+unsigned short g_usHeadDR = 0;
+unsigned short g_usHeadIR = 0;
+unsigned short g_usTailDR = 0;
+unsigned short g_usTailIR = 0;
+
+/***************************************************************
+ *
+ * Global variable to store the number of bits of data or instruction
+ * to be shifted into or out from the device.
+ *
+ ***************************************************************/
+
+unsigned short g_usiDataSize = 0;
+
+/***************************************************************
+ *
+ * Stores the frequency. Default to 1 MHz.
+ *
+ ***************************************************************/
+
+int g_iFrequency = 1000;
+
+/***************************************************************
+ *
+ * Stores the maximum amount of ram needed to hold a row of data.
+ *
+ ***************************************************************/
+
+unsigned short g_usMaxSize = 0;
+
+/***************************************************************
+ *
+ * Stores the LSH or RSH value.
+ *
+ ***************************************************************/
+
+unsigned short g_usShiftValue = 0;
+
+/***************************************************************
+ *
+ * Stores the current repeat loop value.
+ *
+ ***************************************************************/
+
+unsigned short g_usRepeatLoops = 0;
+
+/***************************************************************
+ *
+ * Stores the current vendor.
+ *
+ ***************************************************************/
+
+signed char g_cVendor = LATTICE;
+
+/***************************************************************
+ *
+ * Stores the VME file CRC.
+ *
+ ***************************************************************/
+
+unsigned short g_usCalculatedCRC = 0;
+
+/***************************************************************
+ *
+ * Stores the Device Checksum.
+ *
+ ***************************************************************/
+//08/28/08 NN Added Calculate checksum support.
+unsigned long g_usChecksum = 0;
+unsigned int g_uiChecksumIndex = 0;
+
+/***************************************************************
+ *
+ * Stores the current state of the JTAG state machine.
+ *
+ ***************************************************************/
+
+signed char g_cCurrentJTAGState = 0;
+
+/***************************************************************
+ *
+ * Global variables used to support looping.
+ *
+ * g_pucHeapMemory: holds the entire repeat loop.
+ * g_iHeapCounter: points to the current byte in the repeat loop.
+ * g_iHEAPSize: the current size of the repeat in bytes.
+ *
+ ***************************************************************/
+
+unsigned char * g_pucHeapMemory = NULL;
+unsigned short g_iHeapCounter = 0;
+unsigned short g_iHEAPSize = 0;
+
+/***************************************************************
+ *
+ * Global variables used to support intelligent programming.
+ *
+ * g_usIntelDataIndex: points to the current byte of the
+ * intelligent buffer.
+ * g_usIntelBufferSize: holds the size of the intelligent
+ * buffer.
+ *
+ ***************************************************************/
+
+unsigned short g_usIntelDataIndex = 0;
+unsigned short g_usIntelBufferSize = 0;
+
+/****************************************************************************
+ *
+ * Holds the maximum size of each respective buffer. These variables are used
+ * to write the HEX files when converting VME to HEX.
+ *
+ *****************************************************************************/
+
+unsigned short g_usTDOSize = 0;
+unsigned short g_usMASKSize = 0;
+unsigned short g_usTDISize = 0;
+unsigned short g_usDMASKSize = 0;
+unsigned short g_usLCOUNTSize = 0;
+unsigned short g_usHDRSize = 0;
+unsigned short g_usTDRSize = 0;
+unsigned short g_usHIRSize = 0;
+unsigned short g_usTIRSize = 0;
+unsigned short g_usHeapSize = 0;
+
+/***************************************************************
+ *
+ * Global variables used to store data.
+ *
+ * g_pucOutMaskData: local RAM to hold one row of MASK data.
+ * g_pucInData: local RAM to hold one row of TDI data.
+ * g_pucOutData: local RAM to hold one row of TDO data.
+ * g_pucHIRData: local RAM to hold the current SIR header.
+ * g_pucTIRData: local RAM to hold the current SIR trailer.
+ * g_pucHDRData: local RAM to hold the current SDR header.
+ * g_pucTDRData: local RAM to hold the current SDR trailer.
+ * g_pucIntelBuffer: local RAM to hold the current intelligent buffer.
+ * g_pucOutDMaskData: local RAM to hold one row of DMASK data.
+ *
+ ***************************************************************/
+
+unsigned char * g_pucOutMaskData = NULL,
+ * g_pucInData = NULL,
+ * g_pucOutData = NULL,
+ * g_pucHIRData = NULL,
+ * g_pucTIRData = NULL,
+ * g_pucHDRData = NULL,
+ * g_pucTDRData = NULL,
+ * g_pucIntelBuffer = NULL,
+ * g_pucOutDMaskData = NULL;
+
+/***************************************************************
+ *
+ * JTAG state machine transition table.
+ *
+ ***************************************************************/
+
+struct {
+ unsigned char CurState; /* From this state */
+ unsigned char NextState; /* Step to this state */
+ unsigned char Pattern; /* The tragetory of TMS */
+ unsigned char Pulses; /* The number of steps */
+} g_JTAGTransistions[ 25 ] = {
+ { RESET, RESET, 0xFC, 6 }, /* Transitions from RESET */
+ { RESET, IDLE, 0x00, 1 },
+ { RESET, DRPAUSE, 0x50, 5 },
+ { RESET, IRPAUSE, 0x68, 6 },
+ { IDLE, RESET, 0xE0, 3 }, /* Transitions from IDLE */
+ { IDLE, DRPAUSE, 0xA0, 4 },
+ { IDLE, IRPAUSE, 0xD0, 5 },
+ { DRPAUSE, RESET, 0xF8, 5 }, /* Transitions from DRPAUSE */
+ { DRPAUSE, IDLE, 0xC0, 3 },
+ { DRPAUSE, IRPAUSE, 0xF4, 7 },
+ { DRPAUSE, DRPAUSE, 0xE8, 6 }, /* 06/14/06 Support POLING STATUS LOOP*/
+ { IRPAUSE, RESET, 0xF8, 5 }, /* Transitions from IRPAUSE */
+ { IRPAUSE, IDLE, 0xC0, 3 },
+ { IRPAUSE, DRPAUSE, 0xE8, 6 },
+ { DRPAUSE, SHIFTDR, 0x80, 2 }, /* Extra transitions using SHIFTDR */
+ { IRPAUSE, SHIFTDR, 0xE0, 5 },
+ { SHIFTDR, DRPAUSE, 0x80, 2 },
+ { SHIFTDR, IDLE, 0xC0, 3 },
+ { IRPAUSE, SHIFTIR, 0x80, 2 }, /* Extra transitions using SHIFTIR */
+ { SHIFTIR, IRPAUSE, 0x80, 2 },
+ { SHIFTIR, IDLE, 0xC0, 3 },
+ { DRPAUSE, DRCAPTURE, 0xE0, 4 }, /* 11/15/05 Support DRCAPTURE*/
+ { DRCAPTURE, DRPAUSE, 0x80, 2 },
+ { IDLE, DRCAPTURE, 0x80, 2 },
+ { IRPAUSE, DRCAPTURE, 0xE0, 4 }
+};
+
+/***************************************************************
+ *
+ * List to hold all LVDS pairs.
+ *
+ ***************************************************************/
+
+LVDSPair * g_pLVDSList = NULL;
+unsigned short g_usLVDSPairCount = 0;
+
+/***************************************************************
+ *
+ * Function prototypes.
+ *
+ ***************************************************************/
+
+signed char ispVMCode();
+signed char ispVMDataCode();
+long int ispVMDataSize();
+void ispVMData( unsigned char * Data );
+signed char ispVMShift( signed char Code );
+signed char ispVMAmble( signed char Code );
+signed char ispVMLoop( unsigned short a_usLoopCount );
+signed char ispVMBitShift( signed char mode, unsigned short bits );
+void ispVMComment( unsigned short a_usCommentSize );
+void ispVMHeader( unsigned short a_usHeaderSize );
+signed char ispVMLCOUNT( unsigned short a_usCountSize );
+void ispVMClocks( unsigned short Clocks );
+void ispVMBypass( signed char ScanType, unsigned short Bits );
+void ispVMStateMachine( signed char NextState );
+void ispVMStart();
+void ispVMEnd();
+signed char ispVMSend(unsigned short int);
+signed char ispVMRead(unsigned short int);
+signed char ispVMReadandSave(unsigned short int);
+signed char ispVMProcessLVDS( unsigned short a_usLVDSCount );
+
+
+/***************************************************************
+ *
+ * External variables and functions in ispvm_ui.c module
+ *
+ ***************************************************************/
+extern void vme_out_char(unsigned char charOut);
+extern void vme_out_hex(unsigned char hexOut);
+extern void vme_out_string(char *stringOut);
+extern unsigned char GetByte();
+extern void ispVMMemManager( signed char types, unsigned short size );
+
+/***************************************************************
+ *
+ * External variables and functions in hardware.c module
+ *
+ ***************************************************************/
+extern void ispVMDelay( unsigned short int a_usMicroSecondDelay );
+extern unsigned char readPort();
+extern void writePort( unsigned long pins, unsigned char value );
+extern void sclock();
+extern signed char g_cCurrentJTAGState;
+extern const unsigned long g_ucPinTDI;
+extern const unsigned long g_ucPinTCK;
+extern const unsigned long g_ucPinTMS;
+extern const unsigned long g_ucPinENABLE;
+extern const unsigned long g_ucPinTRST;
+extern const unsigned long g_ucPinTDO;
+
+#ifdef VME_DEBUG
+
+/***************************************************************
+ *
+ * GetState
+ *
+ * Returns the state as a string based on the opcode. Only used
+ * for debugging purposes.
+ *
+ ***************************************************************/
+
+const char * GetState( unsigned char a_ucState )
+{
+ switch( a_ucState ) {
+ case RESET:
+ return( "RESET" );
+ case IDLE:
+ return( "IDLE" );
+ case IRPAUSE:
+ return( "IRPAUSE" );
+ case DRPAUSE:
+ return( "DRPAUSE" );
+ case SHIFTIR:
+ return( "SHIFTIR" );
+ case SHIFTDR:
+ return( "SHIFTDR" );
+ case DRCAPTURE:/* 11/15/05 support DRCAPTURE*/
+ return( "DRCAPTURE" );
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/***************************************************************
+ *
+ * PrintData
+ *
+ * Prints the data. Only used for debugging purposes.
+ *
+ ***************************************************************/
+
+void PrintData( unsigned short a_iDataSize, unsigned char * a_pucData )
+{
+ //09/11/07 NN added local variables initialization
+ unsigned short usByteSize = 0;
+ unsigned short usBitIndex = 0;
+ signed short usByteIndex = 0;
+ unsigned char ucByte = 0;
+ unsigned char ucFlipByte = 0;
+
+ if ( a_iDataSize % 8 ) {
+ //09/11/07 NN Type cast mismatch variables
+ usByteSize = (unsigned short)(a_iDataSize / 8 + 1);
+ }
+ else {
+ //09/11/07 NN Type cast mismatch variables
+ usByteSize = (unsigned short)(a_iDataSize / 8);
+ }
+ printf( "(" );
+ //09/11/07 NN Type cast mismatch variables
+ for ( usByteIndex = (signed short)(usByteSize - 1); usByteIndex >= 0; usByteIndex-- ) {
+ ucByte = a_pucData[ usByteIndex ];
+ ucFlipByte = 0x00;
+
+ /***************************************************************
+ *
+ * Flip each byte.
+ *
+ ***************************************************************/
+
+ for ( usBitIndex = 0; usBitIndex < 8; usBitIndex++ ) {
+ ucFlipByte <<= 1;
+ if ( ucByte & 0x1) {
+ ucFlipByte |= 0x1;
+ }
+
+ ucByte >>= 1;
+ }
+
+ /***************************************************************
+ *
+ * Print the flipped byte.
+ *
+ ***************************************************************/
+
+ printf( "%.02X", ucFlipByte );
+ if ( ( usByteSize - usByteIndex ) % 40 == 39 ) {
+ printf( "\n\t\t" );
+ }
+ if(usByteIndex < 0)
+ break;
+ }
+ printf( ")" );
+}
+#endif //VME_DEBUG
+
+/***************************************************************
+ *
+ * ispVMDataSize
+ *
+ * Returns a VME-encoded number, usually used to indicate the
+ * bit length of an SIR/SDR command.
+ *
+ ***************************************************************/
+
+long int ispVMDataSize()
+{
+ //09/11/07 NN added local variables initialization
+ long int iSize = 0;
+ signed char cCurrentByte = 0;
+ signed char cIndex = 0;
+ cIndex = 0;
+ while ( ( cCurrentByte = GetByte() ) & 0x80 ) {
+ iSize |= ( ( long int ) ( cCurrentByte & 0x7F ) ) << cIndex;
+ cIndex += 7;
+ }
+ iSize |= ( ( long int ) ( cCurrentByte & 0x7F ) ) << cIndex;
+ return iSize;
+}
+
+/***************************************************************
+ *
+ * ispVMCode
+ *
+ * This is the heart of the embedded engine. All the high-level opcodes
+ * are extracted here. Once they have been identified, then it
+ * will call other functions to handle the processing.
+ *
+ ***************************************************************/
+
+signed char ispVMCode()
+{
+ //09/11/07 NN added local variables initialization
+ unsigned short iRepeatSize = 0;
+ signed char cOpcode = 0;
+ signed char cRetCode = 0;
+ unsigned char ucState = 0;
+ unsigned short usDelay = 0;
+ unsigned short usToggle = 0;
+ unsigned char usByte = 0;
+
+ /***************************************************************
+ *
+ * Check the compression flag only if this is the first time
+ * this function is entered. Do not check the compression flag if
+ * it is being called recursively from other functions within
+ * the embedded engine.
+ *
+ ***************************************************************/
+
+ if ( !( g_usDataType & LHEAP_IN ) && !( g_usDataType & HEAP_IN ) ) {
+ usByte = GetByte();
+ if ( usByte == 0xf1 ) {
+ g_usDataType |= COMPRESS;
+ }
+ else if ( usByte == 0xf2 ) {
+ g_usDataType &= ~COMPRESS;
+ }
+ else {
+ return VME_INVALID_FILE;
+ }
+ }
+
+ /***************************************************************
+ *
+ * Begin looping through all the VME opcodes.
+ *
+ ***************************************************************/
+
+ while ( ( cOpcode = GetByte() ) >= 0 ) {
+
+ switch ( cOpcode ) {
+ case STATE:
+
+ /***************************************************************
+ *
+ * Step the JTAG state machine.
+ *
+ ***************************************************************/
+
+ ucState = GetByte();
+
+ /***************************************************************
+ *
+ * Step the JTAG state machine to DRCAPTURE to support Looping.
+ *
+ ***************************************************************/
+
+ if ( (g_usDataType & LHEAP_IN) &&
+ (ucState == DRPAUSE ) &&
+ ( g_cCurrentJTAGState == ucState ))
+ {
+ ispVMStateMachine( DRCAPTURE );
+ }
+
+ ispVMStateMachine( ucState );
+
+#ifdef VME_DEBUG
+ if ( g_usDataType & LHEAP_IN ) {
+ printf( "LDELAY %s ", GetState( ucState ) );
+ }
+ else {
+ printf( "STATE %s;\n", GetState( ucState ) );
+ }
+#endif //VME_DEBUG
+ break;
+ case SIR:
+ case SDR:
+ case XSDR:
+
+#ifdef VME_DEBUG
+ switch( cOpcode ) {
+ case SIR:
+ printf( "SIR " );
+ break;
+ case SDR:
+ case XSDR:
+ if ( g_usDataType & LHEAP_IN ) {
+ printf( "LSDR " );
+ }
+ else {
+ printf( "SDR " );
+ }
+ break;
+ }
+#endif //VME_DEBUG
+ /***************************************************************
+ *
+ * Shift in data into the device.
+ *
+ ***************************************************************/
+
+ cRetCode = ispVMShift( cOpcode );
+ if ( cRetCode != 0 ) {
+ return ( cRetCode );
+ }
+ break;
+ case WAIT:
+
+ /***************************************************************
+ *
+ * Observe delay.
+ *
+ ***************************************************************/
+
+ //09/11/07 NN Type cast mismatch variables
+ usDelay = (unsigned short) ispVMDataSize();
+ ispVMDelay( usDelay );
+
+#ifdef VME_DEBUG
+ if ( usDelay & 0x8000 ) {
+
+ /***************************************************************
+ *
+ * Since MSB is set, the delay time must be decoded to
+ * millisecond. The SVF2VME encodes the MSB to represent
+ * millisecond.
+ *
+ ***************************************************************/
+
+ usDelay &= ~0x8000;
+ if ( g_usDataType & LHEAP_IN ) {
+ printf( "%.2E SEC;\n", ( float ) usDelay / 1000 );
+ }
+ else {
+ printf( "RUNTEST %.2E SEC;\n", ( float ) usDelay / 1000 );
+ }
+ }
+ else {
+
+ /***************************************************************
+ *
+ * Since MSB is not set, the delay time is given as microseconds.
+ *
+ ***************************************************************/
+
+ if ( g_usDataType & LHEAP_IN ) {
+ printf( "%.2E SEC;\n", ( float ) usDelay / 1000000 );
+ }
+ else {
+ printf( "RUNTEST %.2E SEC;\n", ( float ) usDelay / 1000000 );
+ }
+ }
+#endif //VME_DEBUG
+ break;
+ case TCK:
+
+ /***************************************************************
+ *
+ * Issue clock toggles.
+ *
+ ***************************************************************/
+
+ //09/11/07 NN Type cast mismatch variables
+ usToggle = (unsigned short) ispVMDataSize();
+ ispVMClocks( usToggle );
+
+#ifdef VME_DEBUG
+ printf( "RUNTEST %d TCK;\n", usToggle );
+#endif //VME_DEBUG
+ break;
+ case ENDDR:
+
+ /***************************************************************
+ *
+ * Set the ENDDR.
+ *
+ ***************************************************************/
+
+ g_ucEndDR = GetByte();
+
+#ifdef VME_DEBUG
+ printf( "ENDDR %s;\n", GetState( g_ucEndDR ) );
+#endif //VME_DEBUG
+ break;
+ case ENDIR:
+
+ /***************************************************************
+ *
+ * Set the ENDIR.
+ *
+ ***************************************************************/
+
+ g_ucEndIR = GetByte();
+
+#ifdef VME_DEBUG
+ printf( "ENDIR %s;\n", GetState( g_ucEndIR ) );
+#endif //VME_DEBUG
+ break;
+ case HIR:
+ case TIR:
+ case HDR:
+ case TDR:
+
+#ifdef VME_DEBUG
+ switch( cOpcode ) {
+ case HIR:
+ printf( "HIR " );
+ break;
+ case TIR:
+ printf( "TIR " );
+ break;
+ case HDR:
+ printf( "HDR " );
+ break;
+ case TDR:
+ printf( "TDR " );
+ break;
+ }
+#endif //VME_DEBUG
+
+ /***************************************************************
+ *
+ * Set the header/trailer of the device in order to bypass
+ * successfully.
+ *
+ ***************************************************************/
+
+ cRetCode = ispVMAmble( cOpcode );
+ if ( cRetCode != 0 ) {
+ return ( cRetCode );
+ }
+
+#ifdef VME_DEBUG
+ printf( ";\n" );
+#endif //VME_DEBUG
+ break;
+ case MEM:
+
+ /***************************************************************
+ *
+ * The maximum RAM required to support processing one row of the
+ * VME file.
+ *
+ ***************************************************************/
+
+ //09/11/07 NN Type cast mismatch variables
+ g_usMaxSize = (unsigned short) ispVMDataSize();
+
+#ifdef VME_DEBUG
+ printf( "// MEMSIZE %d\n", g_usMaxSize );
+#endif //VME_DEBUG
+ break;
+ case VENDOR:
+
+ /***************************************************************
+ *
+ * Set the VENDOR type.
+ *
+ ***************************************************************/
+
+ cOpcode = GetByte();
+ switch ( cOpcode ) {
+ case LATTICE:
+#ifdef VME_DEBUG
+ printf( "// VENDOR LATTICE\n" );
+#endif //VME_DEBUG
+ g_cVendor = LATTICE;
+ break;
+ case ALTERA:
+#ifdef VME_DEBUG
+ printf( "// VENDOR ALTERA\n" );
+#endif //VME_DEBUG
+ g_cVendor = ALTERA;
+ break;
+ case XILINX:
+#ifdef VME_DEBUG
+ printf( "// VENDOR XILINX\n" );
+#endif //VME_DEBUG
+ g_cVendor = XILINX;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SETFLOW:
+
+ /***************************************************************
+ *
+ * Set the flow control. Flow control determines the personality
+ * of the embedded engine.
+ *
+ ***************************************************************/
+
+ //09/11/07 NN Type cast mismatch variables
+ g_usFlowControl |= (unsigned short) ispVMDataSize();
+ break;
+ case RESETFLOW:
+
+ /***************************************************************
+ *
+ * Unset the flow control.
+ *
+ ***************************************************************/
+
+ //09/11/07 NN Type cast mismatch variables
+ g_usFlowControl &= (unsigned short) ~( ispVMDataSize() );
+ break;
+ case HEAP:
+
+ /***************************************************************
+ *
+ * Allocate heap size to store loops.
+ *
+ ***************************************************************/
+
+ cRetCode = GetByte();
+ if ( cRetCode != SECUREHEAP ) {
+ return VME_INVALID_FILE;
+ }
+ //09/11/07 NN Type cast mismatch variables
+ g_iHEAPSize = (unsigned short) ispVMDataSize();
+
+ /****************************************************************************
+ *
+ * Store the maximum size of the HEAP buffer. Used to convert VME to HEX.
+ *
+ *****************************************************************************/
+
+ if ( g_iHEAPSize > g_usHeapSize ) {
+ g_usHeapSize = g_iHEAPSize;
+ }
+
+ ispVMMemManager( HEAP, ( unsigned short ) g_iHEAPSize );
+ break;
+ case REPEAT:
+
+ /***************************************************************
+ *
+ * Execute loops.
+ *
+ ***************************************************************/
+
+ g_usRepeatLoops = 0;
+
+ //09/11/07 NN Type cast mismatch variables
+ iRepeatSize = (unsigned short) ispVMDataSize();
+
+ cRetCode = ispVMLoop( ( unsigned short ) iRepeatSize );
+ if ( cRetCode != 0 ) {
+ return ( cRetCode );
+ }
+ break;
+ case ENDLOOP:
+
+ /***************************************************************
+ *
+ * Exit point from processing loops.
+ *
+ ***************************************************************/
+
+ return ( cRetCode );
+ case ENDVME:
+
+ /***************************************************************
+ *
+ * The only valid exit point that indicates end of programming.
+ *
+ ***************************************************************/
+
+ return ( cRetCode );
+ case SHR:
+
+ /***************************************************************
+ *
+ * Right-shift address.
+ *
+ ***************************************************************/
+
+ g_usFlowControl |= SHIFTRIGHT;
+
+ //09/11/07 NN Type cast mismatch variables
+ g_usShiftValue = (unsigned short) (g_usRepeatLoops * (unsigned short)GetByte());
+ break;
+ case SHL:
+
+ /***************************************************************
+ *
+ * Left-shift address.
+ *
+ ***************************************************************/
+
+ g_usFlowControl |= SHIFTLEFT;
+
+ //09/11/07 NN Type cast mismatch variables
+ g_usShiftValue = (unsigned short)(g_usRepeatLoops * (unsigned short)GetByte());
+ break;
+ case FREQUENCY:
+
+ /***************************************************************
+ *
+ * Set the frequency.
+ *
+ ***************************************************************/
+
+ //09/11/07 NN Type cast mismatch variables
+ g_iFrequency = (int) (ispVMDataSize() );
+ //10/23/08 NN changed to check if the frequency smaller than 1000
+ if(g_iFrequency >= 1000)
+ {
+ g_iFrequency = g_iFrequency / 1000;
+ if(g_iFrequency == 1)
+ g_iFrequency = 1000;
+#ifdef VME_DEBUG
+ printf( "FREQUENCY %.2E HZ;\n", ( float ) g_iFrequency * 1000 );
+#endif //VME_DEBUG
+ }
+ else
+ {
+ if(g_iFrequency == 0)
+ g_iFrequency = 1000;
+#ifdef VME_DEBUG
+ printf( "FREQUENCY %.2E HZ;\n", ( float ) g_iFrequency );
+#endif //VME_DEBUG
+ }
+ break;
+ case LCOUNT:
+
+ /***************************************************************
+ *
+ * Process LCOUNT command.
+ *
+ ***************************************************************/
+
+ cRetCode = ispVMLCOUNT( ( unsigned short ) ispVMDataSize() );
+ if ( cRetCode != 0 ) {
+ return ( cRetCode );
+ }
+ break;
+ case VUES:
+
+ /***************************************************************
+ *
+ * Set the flow control to verify USERCODE.
+ *
+ ***************************************************************/
+
+ g_usFlowControl |= VERIFYUES;
+ break;
+ case COMMENT:
+
+ /***************************************************************
+ *
+ * Display comment.
+ *
+ ***************************************************************/
+
+ ispVMComment( ( unsigned short ) ispVMDataSize() );
+ break;
+ case LVDS:
+
+ /***************************************************************
+ *
+ * Process LVDS command.
+ *
+ ***************************************************************/
+
+ ispVMProcessLVDS( ( unsigned short ) ispVMDataSize() );
+ break;
+ case HEADER:
+
+ /***************************************************************
+ *
+ * Discard header.
+ *
+ ***************************************************************/
+
+ ispVMHeader( ( unsigned short ) ispVMDataSize() );
+ break;
+ /* 03/14/06 Support Toggle ispENABLE signal*/
+ case ispEN:
+ ucState = GetByte();
+ if((ucState == ON)||(ucState == 0x01))
+ writePort( g_ucPinENABLE, 0x01 );
+ else
+ writePort( g_ucPinENABLE, 0x00 );
+ ispVMDelay( 1 );
+ break;
+ /* 05/24/06 support Toggle TRST pin*/
+ case TRST:
+ ucState = GetByte();
+ if(ucState == 0x01)
+ writePort( g_ucPinTRST, 0x01 );
+ else
+ writePort( g_ucPinTRST, 0x00 );
+ ispVMDelay( 1 );
+ break;
+ default:
+
+ /***************************************************************
+ *
+ * Invalid opcode encountered.
+ *
+ ***************************************************************/
+
+#ifdef VME_DEBUG
+ printf( "\nINVALID OPCODE: 0x%.2X\n", cOpcode );
+#endif //VME_DEBUG
+
+ return VME_INVALID_FILE;
+ }
+ }
+
+ /***************************************************************
+ *
+ * Invalid exit point. Processing the token 'ENDVME' is the only
+ * valid way to exit the embedded engine.
+ *
+ ***************************************************************/
+
+ return ( VME_INVALID_FILE );
+}
+
+/***************************************************************
+ *
+ * ispVMDataCode
+ *
+ * Processes the TDI/TDO/MASK/DMASK etc of an SIR/SDR command.
+ *
+ ***************************************************************/
+
+signed char ispVMDataCode()
+{
+ //09/11/07 NN added local variables initialization
+ signed char cDataByte = 0;
+ signed char siDataSource = 0; /*source of data from file by default*/
+
+ if ( g_usDataType & HEAP_IN ) {
+ siDataSource = 1; /*the source of data from memory*/
+ }
+
+ /****************************************************************************
+ *
+ * Clear the data type register.
+ *
+ *****************************************************************************/
+
+ g_usDataType &= ~( MASK_DATA + TDI_DATA + TDO_DATA + DMASK_DATA + CMASK_DATA );
+
+ /****************************************************************************
+ *
+ * Iterate through SIR/SDR command and look for TDI, TDO, MASK, etc.
+ *
+ *****************************************************************************/
+
+ while ( ( cDataByte = GetByte() ) >= 0 ) {
+
+ ispVMMemManager( cDataByte, g_usMaxSize );
+ switch ( cDataByte ) {
+ case TDI:
+
+ /****************************************************************************
+ *
+ * Store the maximum size of the TDI buffer. Used to convert VME to HEX.
+ *
+ *****************************************************************************/
+
+ if ( g_usiDataSize > g_usTDISize ) {
+ g_usTDISize = g_usiDataSize;
+ }
+ /****************************************************************************
+ *
+ * Updated data type register to indicate that TDI data is currently being
+ * used. Process the data in the VME file into the TDI buffer.
+ *
+ *****************************************************************************/
+
+ g_usDataType |= TDI_DATA;
+ ispVMData( g_pucInData );
+ break;
+ case XTDO:
+
+ /****************************************************************************
+ *
+ * Store the maximum size of the TDO buffer. Used to convert VME to HEX.
+ *
+ *****************************************************************************/
+
+ if ( g_usiDataSize > g_usTDOSize ) {
+ g_usTDOSize = g_usiDataSize;
+ }
+
+ /****************************************************************************
+ *
+ * Updated data type register to indicate that TDO data is currently being
+ * used.
+ *
+ *****************************************************************************/
+
+ g_usDataType |= TDO_DATA;
+ break;
+ case TDO:
+
+ /****************************************************************************
+ *
+ * Store the maximum size of the TDO buffer. Used to convert VME to HEX.
+ *
+ *****************************************************************************/
+
+ if ( g_usiDataSize > g_usTDOSize ) {
+ g_usTDOSize = g_usiDataSize;
+ }
+
+ /****************************************************************************
+ *
+ * Updated data type register to indicate that TDO data is currently being
+ * used. Process the data in the VME file into the TDO buffer.
+ *
+ *****************************************************************************/
+
+ g_usDataType |= TDO_DATA;
+ ispVMData( g_pucOutData );
+ break;
+ case MASK:
+
+ /****************************************************************************
+ *
+ * Store the maximum size of the MASK buffer. Used to convert VME to HEX.
+ *
+ *****************************************************************************/
+
+ if ( g_usiDataSize > g_usMASKSize ) {
+ g_usMASKSize = g_usiDataSize;
+ }
+
+ /****************************************************************************
+ *
+ * Updated data type register to indicate that MASK data is currently being
+ * used. Process the data in the VME file into the MASK buffer.
+ *
+ *****************************************************************************/
+
+ g_usDataType |= MASK_DATA;
+ ispVMData( g_pucOutMaskData );
+ break;
+ case DMASK:
+
+ /****************************************************************************
+ *
+ * Store the maximum size of the DMASK buffer. Used to convert VME to HEX.
+ *
+ *****************************************************************************/
+
+ if ( g_usiDataSize > g_usDMASKSize ) {
+ g_usDMASKSize = g_usiDataSize;
+ }
+
+ /****************************************************************************
+ *
+ * Updated data type register to indicate that DMASK data is currently being
+ * used. Process the data in the VME file into the DMASK buffer.
+ *
+ *****************************************************************************/
+
+ g_usDataType |= DMASK_DATA;
+ ispVMData( g_pucOutDMaskData );
+ break;
+ case CMASK:
+
+ /****************************************************************************
+ *
+ * Updated data type register to indicate that CMASK data is currently being
+ * used. Process the data in the VME file into the CMASK buffer.
+ *
+ *****************************************************************************/
+
+ g_usDataType |= CMASK_DATA;
+ ispVMData( g_pucOutMaskData );
+ break;
+ case CONTINUE:
+ return ( 0 );
+ default:
+
+ /****************************************************************************
+ *
+ * Encountered invalid opcode.
+ *
+ *****************************************************************************/
+
+ return ( VME_INVALID_FILE );
+ }
+
+ switch ( cDataByte ) {
+ case TDI:
+
+ /****************************************************************************
+ *
+ * Left bit shift. Used when performing algorithm looping.
+ *
+ *****************************************************************************/
+
+ if ( g_usFlowControl & SHIFTLEFT ) {
+ ispVMBitShift( SHL, g_usShiftValue );
+ g_usFlowControl &= ~SHIFTLEFT;
+ }
+
+ /****************************************************************************
+ *
+ * Right bit shift. Used when performing algorithm looping.
+ *
+ *****************************************************************************/
+
+ if ( g_usFlowControl & SHIFTRIGHT ) {
+ ispVMBitShift( SHR, g_usShiftValue );
+ g_usFlowControl &= ~SHIFTRIGHT;
+ }
+ default:
+ break;
+ }
+
+ if ( siDataSource ) {
+ g_usDataType |= HEAP_IN; /*restore data from memory*/
+ }
+ }
+
+ if ( siDataSource ) { /*fetch data from heap memory upon return*/
+ g_usDataType |= HEAP_IN;
+ }
+
+ if ( cDataByte < 0 ) {
+
+ /****************************************************************************
+ *
+ * Encountered invalid opcode.
+ *
+ *****************************************************************************/
+
+ return ( VME_INVALID_FILE );
+ }
+ else {
+ return ( 0 );
+ }
+}
+
+/***************************************************************
+ *
+ * ispVMData
+ * Extract one row of data operand from the current data type opcode. Perform
+ * the decompression if necessary. Extra RAM is not required for the
+ * decompression process. The decompression scheme employed in this module
+ * is on row by row basis. The format of the data stream:
+ * [compression code][compressed data stream]
+ * 0x00 --No compression
+ * 0x01 --Compress by 0x00.
+ * Example:
+ * Original stream: 0x000000000000000000000001
+ * Compressed stream: 0x01000901
+ * Detail: 0x01 is the code, 0x00 is the key,
+ * 0x09 is the count of 0x00 bytes,
+ * 0x01 is the uncompressed byte.
+ * 0x02 --Compress by 0xFF.
+ * Example:
+ * Original stream: 0xFFFFFFFFFFFFFFFFFFFFFF01
+ * Compressed stream: 0x02FF0901
+ * Detail: 0x02 is the code, 0xFF is the key,
+ * 0x09 is the count of 0xFF bytes,
+ * 0x01 is the uncompressed byte.
+ * 0x03
+ * : :
+ * 0xFE -- Compress by nibble blocks.
+ * Example:
+ * Original stream: 0x84210842108421084210
+ * Compressed stream: 0x0584210
+ * Detail: 0x05 is the code, means 5 nibbles block.
+ * 0x84210 is the 5 nibble blocks.
+ * The whole row is 80 bits given by g_usiDataSize.
+ * The number of times the block repeat itself
+ * is found by g_usiDataSize/(4*0x05) which is 4.
+ * 0xFF -- Compress by the most frequently happen byte.
+ * Example:
+ * Original stream: 0x04020401030904040404
+ * Compressed stream: 0xFF04(0,1,0x02,0,1,0x01,1,0x03,1,0x09,0,0,0)
+ * or: 0xFF044090181C240
+ * Detail: 0xFF is the code, 0x04 is the key.
+ * a bit of 0 represent the key shall be put into
+ * the current bit position and a bit of 1
+ * represent copying the next of 8 bits of data
+ * in.
+ *
+ ***************************************************************/
+
+void ispVMData( unsigned char * ByteData )
+{
+ //09/11/07 NN added local variables initialization
+ unsigned short size = 0;
+ unsigned short i, j, m, getData = 0;
+ unsigned char cDataByte = 0;
+ unsigned char compress = 0;
+ unsigned short FFcount = 0;
+ unsigned char compr_char = 0xFF;
+ unsigned short index = 0;
+ signed char compression = 0;
+
+ /*convert number in bits to bytes*/
+ if (g_usiDataSize%8>0) {
+ //09/11/07 NN Type cast mismatch variables
+ size = (unsigned short)(g_usiDataSize/8 + 1);
+ }
+ else {
+ //09/11/07 NN Type cast mismatch variables
+ size = (unsigned short)(g_usiDataSize/8);
+ }
+
+ /* If there is compression, then check if compress by key of 0x00 or 0xFF
+ or by other keys or by nibble blocks*/
+
+ if ( g_usDataType & COMPRESS ) {
+ compression = 1;
+ if ( ( ( compress = GetByte() ) == VAR ) && ( g_usDataType & HEAP_IN ) ) {
+ getData = 1;
+ g_usDataType &= ~(HEAP_IN);
+ compress = GetByte();
+ }
+
+ switch (compress){
+ case 0x00:
+ /* No compression */
+ compression = 0;
+ break;
+ case 0x01:
+ /* Compress by byte 0x00 */
+ compr_char = 0x00;
+ break;
+ case 0x02:
+ /* Compress by byte 0xFF */
+ compr_char = 0xFF;
+ break;
+ case 0xFF:
+ /* Huffman encoding */
+ compr_char = GetByte();
+ i = 8;
+ for ( index = 0; index < size; index++ ) {
+ ByteData[ index ] = 0x00;
+ if ( i > 7 ) {
+ cDataByte = GetByte();
+ i = 0;
+ }
+ if ((cDataByte << i++) & 0x80)
+ m = 8;
+ else {
+ ByteData[index] = compr_char;
+ m = 0;
+ }
+
+ for (j = 0; j < m; j++) {
+ if (i > 7) {
+ cDataByte = GetByte();
+ i = 0;
+ }
+ ByteData[index] |=((cDataByte << i++)&0x80) >> j;
+ }
+ }
+ size = 0;
+ break;
+ default:
+ for (index = 0; index < size; index++)
+ ByteData[index] = 0x00;
+ for (index = 0; index < compress; index++) {
+ if (index%2 == 0)
+ cDataByte = GetByte();
+ for (i = 0; i < size*2/compress; i++){
+ //09/11/07 NN Type cast mismatch variables
+ j = (unsigned short)(index + (i*(unsigned short)compress));
+ /*clear the nibble to zero first*/
+ if (j%2) {
+ if (index%2)
+ ByteData[j/2] |= cDataByte & 0x0F;
+ else
+ ByteData[j/2] |= cDataByte >> 4;
+ }
+ else {
+ if (index%2)
+ ByteData[j/2] |= cDataByte << 4;
+ else
+ ByteData[j/2] |= cDataByte & 0xF0;
+ }
+ }
+ }
+ size = 0;
+ break;
+ }
+ }
+
+ FFcount = 0;
+
+ /* Decompress by byte 0x00 or 0xFF */
+ for (index = 0; index < size; index++) {
+ if (FFcount <= 0) {
+ cDataByte = GetByte();
+ if ((cDataByte == VAR) && (g_usDataType&HEAP_IN) && !getData && !(g_usDataType&COMPRESS)) {
+ getData = 1;
+ g_usDataType &= ~(HEAP_IN);
+ cDataByte = GetByte();
+ }
+ ByteData[index] = cDataByte;
+ if ((compression) &&(cDataByte == compr_char)) /*decompression is on*/
+ //09/11/07 NN Type cast mismatch variables
+ FFcount = (unsigned short) ispVMDataSize(); /*The number of 0xFF or 0x00 bytes*/
+ }
+ else {
+ FFcount--; /*Use up the 0xFF chain first*/
+ ByteData[index] = compr_char;
+ }
+ }
+
+ if (getData) {
+ g_usDataType |= HEAP_IN;
+ getData = 0;
+ }
+}
+
+/***************************************************************
+ *
+ * ispVMShift
+ *
+ * Processes the SDR/XSDR/SIR commands.
+ *
+ ***************************************************************/
+
+signed char ispVMShift( signed char a_cCode )
+{
+ //09/11/07 NN added local variables initialization
+ unsigned short iDataIndex = 0;
+ unsigned short iReadLoop = 0;
+ signed char cRetCode = 0;
+
+ cRetCode=0;
+ //09/11/07 NN Type cast mismatch variables
+ g_usiDataSize = (unsigned short) ispVMDataSize();
+
+ g_usDataType &= ~( SIR_DATA + EXPRESS + SDR_DATA ); /*clear the flags first*/
+ switch ( a_cCode ) {
+ case SIR:
+ g_usDataType |= SIR_DATA;
+ /* 1/15/04 If performing cascading, then go directly to SHIFTIR. Else,
+ go to IRPAUSE before going to SHIFTIR */
+ if ( g_usFlowControl & CASCADE ) {
+ ispVMStateMachine( SHIFTIR );
+ }
+ else {
+ ispVMStateMachine( IRPAUSE );
+ ispVMStateMachine( SHIFTIR );
+ if ( g_usHeadIR > 0 ){
+ ispVMBypass( HIR, g_usHeadIR );
+ sclock();
+ }
+ }
+ break;
+ case XSDR:
+ g_usDataType |= EXPRESS; /*mark simultaneous in and out*/
+ /* FALLTHRU */
+ case SDR:
+ g_usDataType |= SDR_DATA;
+ /* 1/15/04 If already in SHIFTDR, then do not move state or shift in header.
+ This would imply that the previously shifted frame was a cascaded frame. */
+ if ( g_cCurrentJTAGState != SHIFTDR ) {
+ /* 1/15/04 If performing cascading, then go directly to SHIFTDR. Else,
+ go to DRPAUSE before going to SHIFTDR */
+ if ( g_usFlowControl & CASCADE ) {
+ if ( g_cCurrentJTAGState == DRPAUSE ) {
+ ispVMStateMachine( SHIFTDR );
+ /* 1/15/04 If cascade flag has been set and the current state is
+ DRPAUSE, this implies that the first cascaded frame is about to
+ be shifted in. The header must be shifted prior to shifting
+ the first cascaded frame. */
+ if ( g_usHeadDR > 0 ) {
+ ispVMBypass( HDR, g_usHeadDR );
+ sclock();
+ }
+ }
+ else {
+ ispVMStateMachine( SHIFTDR );
+ }
+ }
+ else {
+ ispVMStateMachine( DRPAUSE );
+ ispVMStateMachine( SHIFTDR );
+ if ( g_usHeadDR > 0 ) {
+ ispVMBypass( HDR, g_usHeadDR );
+ sclock();
+ }
+ }
+ }
+ break;
+ default:
+ return ( VME_INVALID_FILE );
+ }
+
+ cRetCode = ispVMDataCode();
+
+ if ( cRetCode != 0 ) {
+ return ( VME_INVALID_FILE );
+ }
+
+#ifdef VME_DEBUG
+ printf( "%d ", g_usiDataSize );
+
+ if ( g_usDataType & TDI_DATA ) {
+ printf( "TDI " );
+ PrintData( g_usiDataSize, g_pucInData );
+ }
+
+ if ( g_usDataType & TDO_DATA ) {
+ printf( "\n\t\tTDO " );
+ PrintData( g_usiDataSize, g_pucOutData );
+ }
+
+ if ( g_usDataType & MASK_DATA ) {
+ printf( "\n\t\tMASK " );
+ PrintData( g_usiDataSize, g_pucOutMaskData );
+ }
+
+ if ( g_usDataType & DMASK_DATA ) {
+ printf( "\n\t\tDMASK " );
+ PrintData( g_usiDataSize, g_pucOutDMaskData );
+ }
+
+ printf( ";\n" );
+#endif //VME_DEBUG
+
+ if ( g_usDataType & TDO_DATA || g_usDataType & DMASK_DATA ) {
+ if(g_usDataType & DMASK_DATA){
+ cRetCode = ispVMReadandSave( g_usiDataSize );
+ if(!cRetCode){
+ if ( g_usTailDR > 0 ) {
+ sclock();
+ ispVMBypass( TDR, g_usTailDR );
+ }
+ ispVMStateMachine( DRPAUSE );
+ ispVMStateMachine( SHIFTDR );
+ if( g_usHeadDR > 0 ){
+ ispVMBypass( HDR, g_usHeadDR );
+ sclock();
+ }
+ for ( iDataIndex=0; iDataIndex < g_usiDataSize / 8 + 1; iDataIndex++ )
+ g_pucInData[ iDataIndex ] = g_pucOutData[ iDataIndex ];
+ g_usDataType &= ~( TDO_DATA+ DMASK_DATA );
+ cRetCode = ispVMSend( g_usiDataSize );
+ }
+ }
+ else{
+ cRetCode = ispVMRead( g_usiDataSize );
+ if ( cRetCode == -1 && g_cVendor == XILINX ) {
+ for( iReadLoop = 0; iReadLoop < 30; iReadLoop++ ){
+ cRetCode = ispVMRead( g_usiDataSize );
+ if( !cRetCode ) {
+ break;
+ }
+ else {
+ ispVMStateMachine( DRPAUSE ); /*Always DRPAUSE*/
+ /*Bypass other devices when appropriate*/
+ ispVMBypass( TDR, g_usTailDR );
+ ispVMStateMachine( g_ucEndDR );
+ ispVMStateMachine( IDLE );
+ ispVMDelay( 0x8001 );
+ }
+ }
+ }
+ }
+ }
+ else { /*TDI only*/
+ cRetCode = ispVMSend( g_usiDataSize );
+ }
+
+ /*transfer the input data to the output buffer for the next verify*/
+ if ( ( g_usDataType & EXPRESS ) || ( a_cCode == SDR ) ) {
+ if ( g_pucOutData ) {
+ for ( iDataIndex=0; iDataIndex < g_usiDataSize / 8 + 1; iDataIndex++ )
+ g_pucOutData[ iDataIndex ] = g_pucInData[ iDataIndex ];
+ }
+ }
+
+ switch( a_cCode ) {
+ case SIR:
+ /* 1/15/04 If not performing cascading, then shift ENDIR */
+ if ( !( g_usFlowControl & CASCADE ) ) {
+ if ( g_usTailIR > 0 ) {
+ sclock();
+ ispVMBypass( TIR, g_usTailIR );
+ }
+ ispVMStateMachine( g_ucEndIR );
+ }
+ break;
+ case XSDR:
+ case SDR:
+ /* 1/15/04 If not performing cascading, then shift ENDDR */
+ if ( !( g_usFlowControl & CASCADE ) ) {
+ if ( g_usTailDR > 0 ) {
+ sclock();
+ ispVMBypass( TDR, g_usTailDR );
+ }
+ ispVMStateMachine( g_ucEndDR );
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ( cRetCode );
+}
+
+/***************************************************************
+ *
+ * ispVMAmble
+ *
+ * This routine is to extract Header and Trailer parameter for SIR and
+ * SDR operations.
+ *
+ * The Header and Trailer parameter are the pre-amble and post-amble bit
+ * stream need to be shifted into TDI or out of TDO of the devices. Mostly
+ * is for the purpose of bypassing the leading or trailing devices. ispVM
+ * supports only shifting data into TDI to bypass the devices.
+ *
+ * For a single device, the header and trailer parameters are all set to 0
+ * as default by ispVM. If it is for multiple devices, the header and trailer
+ * value will change as specified by the VME file.
+ *
+ ***************************************************************/
+
+signed char ispVMAmble( signed char Code )
+{
+ signed char compress = 0;
+ //09/11/07 NN Type cast mismatch variables
+ g_usiDataSize = (unsigned short)ispVMDataSize();
+
+#ifdef VME_DEBUG
+ printf( "%d", g_usiDataSize );
+#endif //VME_DEBUG
+
+ if ( g_usiDataSize ) {
+
+ /****************************************************************************
+ *
+ * Discard the TDI byte and set the compression bit in the data type register
+ * to false if compression is set because TDI data after HIR/HDR/TIR/TDR is not
+ * compressed.
+ *
+ *****************************************************************************/
+
+ GetByte();
+ if ( g_usDataType & COMPRESS ) {
+ g_usDataType &= ~( COMPRESS );
+ compress = 1;
+ }
+ }
+
+ switch ( Code ) {
+ case HIR:
+
+ /****************************************************************************
+ *
+ * Store the maximum size of the HIR buffer. Used to convert VME to HEX.
+ *
+ *****************************************************************************/
+
+ if ( g_usiDataSize > g_usHIRSize ) {
+ g_usHIRSize = g_usiDataSize;
+ }
+
+ /****************************************************************************
+ *
+ * Assign the HIR value and allocate memory.
+ *
+ *****************************************************************************/
+
+ g_usHeadIR = g_usiDataSize;
+ if ( g_usHeadIR ) {
+ ispVMMemManager( HIR, g_usHeadIR );
+ ispVMData( g_pucHIRData );
+
+#ifdef VME_DEBUG
+ printf( " TDI " );
+ PrintData( g_usHeadIR, g_pucHIRData );
+#endif //VME_DEBUG
+ }
+ break;
+ case TIR:
+
+ /****************************************************************************
+ *
+ * Store the maximum size of the TIR buffer. Used to convert VME to HEX.
+ *
+ *****************************************************************************/
+
+ if ( g_usiDataSize > g_usTIRSize ) {
+ g_usTIRSize = g_usiDataSize;
+ }
+
+ /****************************************************************************
+ *
+ * Assign the TIR value and allocate memory.
+ *
+ *****************************************************************************/
+
+ g_usTailIR = g_usiDataSize;
+ if ( g_usTailIR ) {
+ ispVMMemManager( TIR, g_usTailIR );
+ ispVMData( g_pucTIRData );
+
+#ifdef VME_DEBUG
+ printf( " TDI " );
+ PrintData( g_usTailIR, g_pucTIRData );
+#endif //VME_DEBUG
+ }
+ break;
+ case HDR:
+
+ /****************************************************************************
+ *
+ * Store the maximum size of the HDR buffer. Used to convert VME to HEX.
+ *
+ *****************************************************************************/
+
+ if ( g_usiDataSize > g_usHDRSize ) {
+ g_usHDRSize = g_usiDataSize;
+ }
+
+ /****************************************************************************
+ *
+ * Assign the HDR value and allocate memory.
+ *
+ *****************************************************************************/
+
+ g_usHeadDR = g_usiDataSize;
+ if ( g_usHeadDR ) {
+ ispVMMemManager( HDR, g_usHeadDR );
+ ispVMData( g_pucHDRData );
+
+#ifdef VME_DEBUG
+ printf( " TDI " );
+ PrintData( g_usHeadDR, g_pucHDRData );
+#endif //VME_DEBUG
+ }
+ break;
+ case TDR:
+
+ /****************************************************************************
+ *
+ * Store the maximum size of the TDR buffer. Used to convert VME to HEX.
+ *
+ *****************************************************************************/
+
+ if ( g_usiDataSize > g_usTDRSize ) {
+ g_usTDRSize = g_usiDataSize;
+ }
+
+ /****************************************************************************
+ *
+ * Assign the TDR value and allocate memory.
+ *
+ *****************************************************************************/
+
+ g_usTailDR = g_usiDataSize;
+ if ( g_usTailDR ) {
+ ispVMMemManager( TDR, g_usTailDR );
+ ispVMData( g_pucTDRData );
+
+#ifdef VME_DEBUG
+ printf( " TDI " );
+ PrintData( g_usTailDR, g_pucTDRData );
+#endif //VME_DEBUG
+ }
+ break;
+ default:
+ break;
+ }
+
+ /****************************************************************************
+ *
+ * Re-enable compression if it was previously set.
+ *
+ *****************************************************************************/
+
+ if ( compress ) {
+ g_usDataType |= COMPRESS;
+ }
+
+ if ( g_usiDataSize ) {
+ Code = GetByte();
+ if ( Code == CONTINUE ) {
+ return 0;
+ }
+ else {
+
+ /****************************************************************************
+ *
+ * Encountered invalid opcode.
+ *
+ *****************************************************************************/
+
+ return VME_INVALID_FILE;
+ }
+ }
+
+ return 0;
+}
+
+/***************************************************************
+ *
+ * ispVMLoop
+ *
+ * Perform the function call upon by the REPEAT opcode.
+ * Memory is to be allocated to store the entire loop from REPEAT to ENDLOOP.
+ * After the loop is stored then execution begin. The REPEATLOOP flag is set
+ * on the g_usFlowControl register to indicate the repeat loop is in session
+ * and therefore fetch opcode from the memory instead of from the file.
+ *
+ ***************************************************************/
+
+signed char ispVMLoop(unsigned short a_usLoopCount)
+{
+ //09/11/07 NN added local variables initialization
+ signed char cRetCode = 0;
+ unsigned short iHeapIndex = 0;
+ unsigned short iLoopIndex = 0;
+
+ g_usShiftValue = 0;
+ for ( iHeapIndex = 0; iHeapIndex < g_iHEAPSize; iHeapIndex++ ) {
+ g_pucHeapMemory[ iHeapIndex ] = GetByte();
+ }
+
+ if ( g_pucHeapMemory[ iHeapIndex - 1 ] != ENDLOOP ) {
+ return( VME_INVALID_FILE );
+ }
+
+ g_usFlowControl |= REPEATLOOP;
+ g_usDataType |= HEAP_IN;
+
+ for ( iLoopIndex = 0; iLoopIndex < a_usLoopCount; iLoopIndex++ ) {
+ g_iHeapCounter = 0;
+ cRetCode = ispVMCode();
+ g_usRepeatLoops++;
+ if ( cRetCode < 0 ) {
+ break;
+ }
+ }
+
+ g_usDataType &= ~( HEAP_IN );
+ g_usFlowControl &= ~( REPEATLOOP );
+ return ( cRetCode );
+}
+
+/***************************************************************
+ *
+ * ispVMBitShift
+ *
+ * Shift the TDI stream left or right by the number of bits. The data in
+ * *g_pucInData is of the VME format, so the actual shifting is the reverse of
+ * IEEE 1532 or SVF format.
+ *
+ ***************************************************************/
+
+signed char ispVMBitShift(signed char mode, unsigned short bits)
+{
+ //09/11/07 NN added local variables initialization
+ unsigned short i = 0;
+ unsigned short size = 0;
+ unsigned short tmpbits = 0;
+
+ if (g_usiDataSize%8>0) {
+ //09/11/07 NN Type cast mismatch variables
+ size = (unsigned short)(g_usiDataSize/8 + 1);
+ }
+ else {
+ //09/11/07 NN Type cast mismatch variables
+ size = (unsigned short)(g_usiDataSize/8);
+ }
+
+ switch(mode) {
+ case SHR:
+ for (i = 0; i < size; i++) {
+ if (g_pucInData[i] != 0) {
+ tmpbits = bits;
+ while (tmpbits > 0) {
+ g_pucInData[i] <<= 1;
+ if (g_pucInData[i] == 0) {
+ i--;
+ g_pucInData[i] = 1;
+ }
+ tmpbits--;
+ }
+ }
+ }
+ break;
+ case SHL:
+ for (i = 0; i < size; i++) {
+ if (g_pucInData[i] != 0) {
+ tmpbits = bits;
+ while (tmpbits > 0) {
+ g_pucInData[i] >>= 1;
+ if (g_pucInData[i] == 0) {
+ i--;
+ g_pucInData[i] = 8;
+ }
+ tmpbits--;
+ }
+ }
+ }
+ break;
+ default:
+ return ( VME_INVALID_FILE );
+ }
+
+ return (0);
+}
+
+/***************************************************************
+ *
+ * ispVMComment
+ *
+ * Displays the SVF comments.
+ *
+ ***************************************************************/
+
+void ispVMComment( unsigned short a_usCommentSize )
+{
+ char cCurByte = 0;
+ for ( ; a_usCommentSize > 0; a_usCommentSize-- ) {
+ /****************************************************************************
+ *
+ * Print character to the terminal.
+ *
+ *****************************************************************************/
+ cCurByte = GetByte();
+ vme_out_char( cCurByte );
+ }
+ cCurByte = '\n';
+ vme_out_char(cCurByte );
+}
+
+/***************************************************************
+ *
+ * ispVMHeader
+ *
+ * Iterate the length of the header and discard it.
+ *
+ ***************************************************************/
+
+void ispVMHeader( unsigned short a_usHeaderSize )
+{
+ for ( ; a_usHeaderSize > 0; a_usHeaderSize-- ) {
+ GetByte();
+ }
+}
+
+/***************************************************************
+ *
+ * ispVMCalculateCRC32
+ *
+ * Calculate the 32-bit CRC.
+ *
+ ***************************************************************/
+
+void ispVMCalculateCRC32( unsigned char a_ucData )
+{
+ //09/11/07 NN added local variables initialization
+ unsigned char ucIndex = 0;
+ unsigned char ucFlipData = 0;
+ unsigned short usCRCTableEntry = 0;
+ unsigned int crc_table[ 16 ] = {
+ 0x0000, 0xCC01, 0xD801,
+ 0x1400, 0xF001, 0x3C00,
+ 0x2800, 0xE401, 0xA001,
+ 0x6C00, 0x7800, 0xB401,
+ 0x5000, 0x9C01, 0x8801,
+ 0x4400
+ };
+
+ for ( ucIndex = 0; ucIndex < 8; ucIndex++ ) {
+ ucFlipData <<= 1;
+ if ( a_ucData & 0x01 ) {
+ ucFlipData |= 0x01;
+ }
+ a_ucData >>= 1;
+ }
+
+ //09/11/07 NN Type cast mismatch variables
+ usCRCTableEntry = (unsigned short)(crc_table[ g_usCalculatedCRC & 0xF ]);
+ g_usCalculatedCRC = (unsigned short)(( g_usCalculatedCRC >> 4 ) & 0x0FFF);
+ g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^ usCRCTableEntry ^ crc_table[ ucFlipData & 0xF ]);
+ usCRCTableEntry = (unsigned short)(crc_table[ g_usCalculatedCRC & 0xF ]);
+ g_usCalculatedCRC = (unsigned short)(( g_usCalculatedCRC >> 4 ) & 0x0FFF);
+ g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^ usCRCTableEntry ^ crc_table[ ( ucFlipData >> 4 ) & 0xF ]);
+}
+
+/***************************************************************
+ *
+ * ispVMLCOUNT
+ *
+ * Process the intelligent programming loops.
+ *
+ ***************************************************************/
+
+signed char ispVMLCOUNT( unsigned short a_usCountSize )
+{
+ unsigned short usContinue = 1;
+ unsigned short usIntelBufferIndex = 0;
+ unsigned short usCountIndex = 0;
+ signed char cRetCode = 0;
+ signed char cRepeatHeap = 0;
+ signed char cOpcode = 0;
+ unsigned char ucState = 0;
+ unsigned short usDelay = 0;
+ unsigned short usToggle = 0;
+ // unsigned char usByte = 0;
+
+ g_usIntelBufferSize = (unsigned short)ispVMDataSize();
+
+ /****************************************************************************
+ *
+ * Allocate memory for intel buffer.
+ *
+ *****************************************************************************/
+
+ ispVMMemManager( LHEAP, g_usIntelBufferSize );
+
+ /****************************************************************************
+ *
+ * Store the maximum size of the intelligent buffer. Used to convert VME to HEX.
+ *
+ *****************************************************************************/
+
+ if ( g_usIntelBufferSize > g_usLCOUNTSize ) {
+ g_usLCOUNTSize = g_usIntelBufferSize;
+ }
+
+ /****************************************************************************
+ *
+ * Copy intel data to the buffer.
+ *
+ *****************************************************************************/
+
+ for ( usIntelBufferIndex = 0; usIntelBufferIndex < g_usIntelBufferSize; usIntelBufferIndex++ ) {
+ g_pucIntelBuffer[ usIntelBufferIndex ] = GetByte();
+ }
+
+ /****************************************************************************
+ *
+ * Set the data type register to get data from the intelligent data buffer.
+ *
+ *****************************************************************************/
+
+ g_usDataType |= LHEAP_IN;
+
+ /****************************************************************************
+ *
+ * If the HEAP_IN flag is set, temporarily unset the flag so data will be
+ * retrieved from the status buffer.
+ *
+ *****************************************************************************/
+
+ if ( g_usDataType & HEAP_IN ) {
+ g_usDataType &= ~HEAP_IN;
+ cRepeatHeap = 1;
+ }
+
+#ifdef VME_DEBUG
+ printf( "LCOUNT %d;\n", a_usCountSize );
+#endif //VME_DEBUG
+
+ /****************************************************************************
+ *
+ * Iterate through the intelligent programming command.
+ *
+ *****************************************************************************/
+
+ for ( usCountIndex = 0; usCountIndex < a_usCountSize; usCountIndex++ ) {
+
+ /****************************************************************************
+ *
+ * Initialize the intel data index to 0 before each iteration.
+ *
+ *****************************************************************************/
+
+ g_usIntelDataIndex = 0;
+ cOpcode = 0;
+ ucState = 0;
+ usDelay = 0;
+ usToggle = 0;
+ // usByte = 0;
+ usContinue = 1;
+
+ /***************************************************************
+ *
+ * Begin looping through all the VME opcodes.
+ *
+ ***************************************************************/
+ /***************************************************************
+ * 4/1/09 Nguyen replaced the recursive function call codes on
+ * the ispVMLCOUNT function
+ *
+ ***************************************************************/
+ while ( usContinue )
+ {
+ cOpcode = GetByte();
+ switch ( cOpcode ) {
+ case HIR:
+ case TIR:
+ case HDR:
+ case TDR:
+ /***************************************************************
+ *
+ * Set the header/trailer of the device in order to bypass
+ * successfully.
+ *
+ ***************************************************************/
+
+ ispVMAmble( cOpcode );
+ break;
+ case STATE:
+
+ /***************************************************************
+ *
+ * Step the JTAG state machine.
+ *
+ ***************************************************************/
+
+ ucState = GetByte();
+ /***************************************************************
+ *
+ * Step the JTAG state machine to DRCAPTURE to support Looping.
+ *
+ ***************************************************************/
+
+ if ( (g_usDataType & LHEAP_IN) &&
+ (ucState == DRPAUSE ) &&
+ ( g_cCurrentJTAGState == ucState ))
+ {
+ ispVMStateMachine( DRCAPTURE );
+ }
+ ispVMStateMachine( ucState );
+#ifdef VME_DEBUG
+ printf( "LDELAY %s ", GetState( ucState ) );
+#endif //VME_DEBUG
+ break;
+ case SIR:
+#ifdef VME_DEBUG
+ printf( "SIR " );
+#endif //VME_DEBUG
+ /***************************************************************
+ *
+ * Shift in data into the device.
+ *
+ ***************************************************************/
+
+ cRetCode = ispVMShift( cOpcode );
+ break;
+ case SDR:
+
+#ifdef VME_DEBUG
+ printf( "LSDR " );
+#endif //VME_DEBUG
+ /***************************************************************
+ *
+ * Shift in data into the device.
+ *
+ ***************************************************************/
+
+ cRetCode = ispVMShift( cOpcode );
+ break;
+ case WAIT:
+
+ /***************************************************************
+ *
+ * Observe delay.
+ *
+ ***************************************************************/
+
+ usDelay = (unsigned short)ispVMDataSize();
+ ispVMDelay( usDelay );
+
+#ifdef VME_DEBUG
+ if ( usDelay & 0x8000 ) {
+
+ /***************************************************************
+ *
+ * Since MSB is set, the delay time must be decoded to
+ * millisecond. The SVF2VME encodes the MSB to represent
+ * millisecond.
+ *
+ ***************************************************************/
+
+ usDelay &= ~0x8000;
+ printf( "%.2E SEC;\n", ( float ) usDelay / 1000 );
+ }
+ else {
+
+ /***************************************************************
+ *
+ * Since MSB is not set, the delay time is given as microseconds.
+ *
+ ***************************************************************/
+
+ printf( "%.2E SEC;\n", ( float ) usDelay / 1000000 );
+ }
+#endif //VME_DEBUG
+ break;
+ case TCK:
+
+ /***************************************************************
+ *
+ * Issue clock toggles.
+ *
+ ***************************************************************/
+
+ usToggle = (unsigned short)ispVMDataSize();
+ ispVMClocks( usToggle );
+
+#ifdef VME_DEBUG
+ printf( "RUNTEST %d TCK;\n", usToggle );
+#endif //VME_DEBUG
+ break;
+ case ENDLOOP:
+
+ /***************************************************************
+ *
+ * Exit point from processing loops.
+ *
+ ***************************************************************/
+ usContinue = 0;
+ break;
+
+ case COMMENT:
+
+ /***************************************************************
+ *
+ * Display comment.
+ *
+ ***************************************************************/
+
+ ispVMComment( ( unsigned short ) ispVMDataSize() );
+ break;
+ case ispEN:
+ ucState = GetByte();
+ if((ucState == ON)||(ucState == 0x01))
+ writePort( g_ucPinENABLE, 0x01 );
+ else
+ writePort( g_ucPinENABLE, 0x00 );
+ ispVMDelay( 1 );
+ break;
+ case TRST:
+ if(GetByte() == 0x01)
+ writePort( g_ucPinTRST, 0x01 );
+ else
+ writePort( g_ucPinTRST, 0x00 );
+ ispVMDelay( 1 );
+ break;
+ default:
+
+ /***************************************************************
+ *
+ * Invalid opcode encountered.
+ *
+ ***************************************************************/
+
+#ifdef VME_DEBUG
+ printf( "\nINVALID OPCODE: 0x%.2X\n", cOpcode );
+#endif //VME_DEBUG
+
+ return VME_INVALID_FILE;
+ }
+ }
+ if ( cRetCode >= 0 ) {
+ /****************************************************************************
+ *
+ * Break if intelligent programming is successful.
+ *
+ *****************************************************************************/
+
+ break;
+ }
+
+ }
+ /****************************************************************************
+ *
+ * If HEAP_IN flag was temporarily disabled, re-enable it before exiting.
+ *
+ *****************************************************************************/
+
+ if ( cRepeatHeap ) {
+ g_usDataType |= HEAP_IN;
+ }
+
+ /****************************************************************************
+ *
+ * Set the data type register to not get data from the intelligent data buffer.
+ *
+ *****************************************************************************/
+
+ g_usDataType &= ~LHEAP_IN;
+ return cRetCode;
+}
+
+/***************************************************************
+ *
+ * ispVMClocks
+ *
+ * Applies the specified number of pulses to TCK.
+ *
+ ***************************************************************/
+
+void ispVMClocks( unsigned short Clocks )
+{
+ unsigned short iClockIndex = 0;
+ for ( iClockIndex = 0; iClockIndex < Clocks; iClockIndex++ ) {
+ sclock();
+ }
+}
+
+/***************************************************************
+ *
+ * ispVMBypass
+ *
+ * This procedure takes care of the HIR, HDR, TIR, TDR for the
+ * purpose of putting the other devices into Bypass mode. The
+ * current state is checked to find out if it is at DRPAUSE or
+ * IRPAUSE. If it is at DRPAUSE, perform bypass register scan.
+ * If it is at IRPAUSE, scan into instruction registers the bypass
+ * instruction.
+ *
+ ***************************************************************/
+
+void ispVMBypass( signed char ScanType, unsigned short Bits )
+{
+ //09/11/07 NN added local variables initialization
+ unsigned short iIndex = 0;
+ unsigned short iSourceIndex = 0;
+ unsigned char cBitState = 0;
+ unsigned char cCurByte = 0;
+ unsigned char * pcSource = NULL;
+
+ if ( Bits <= 0 ) {
+ return;
+ }
+
+ switch ( ScanType ) {
+ case HIR:
+ pcSource = g_pucHIRData;
+ break;
+ case TIR:
+ pcSource = g_pucTIRData;
+ break;
+ case HDR:
+ pcSource = g_pucHDRData;
+ break;
+ case TDR:
+ pcSource = g_pucTDRData;
+ break;
+ default:
+ break;
+ }
+ if(pcSource)
+ {
+ iSourceIndex = 0;
+ cBitState = 0;
+ for ( iIndex = 0; iIndex < Bits - 1; iIndex++ ) {
+ /* Scan instruction or bypass register */
+ if ( iIndex % 8 == 0 ) {
+ cCurByte = pcSource[ iSourceIndex++ ];
+ }
+ cBitState = ( unsigned char ) ( ( ( cCurByte << iIndex % 8 ) & 0x80 ) ? 0x01 : 0x00 );
+ writePort( g_ucPinTDI, cBitState );
+ sclock();
+ }
+
+ if ( iIndex % 8 == 0 ) {
+ cCurByte = pcSource[ iSourceIndex++ ];
+ }
+
+ cBitState = ( unsigned char ) ( ( ( cCurByte << iIndex % 8 ) & 0x80 ) ? 0x01 : 0x00 );
+ writePort( g_ucPinTDI, cBitState );
+ }
+}
+
+/***************************************************************
+ *
+ * ispVMStateMachine
+ *
+ * This procedure steps all devices in the daisy chain from a given
+ * JTAG state to the next desirable state. If the next state is TLR,
+ * the JTAG state machine is brute forced into TLR by driving TMS
+ * high and pulse TCK 6 times.
+ *
+ ***************************************************************/
+
+void ispVMStateMachine( signed char cNextJTAGState )
+{
+ //09/11/07 NN added local variables initialization
+ signed char cPathIndex = 0;
+ signed char cStateIndex = 0;
+ short int found = 0;
+
+ if ( ( g_cCurrentJTAGState == cNextJTAGState ) && ( cNextJTAGState != RESET ) ) {
+ return;
+ }
+
+ for ( cStateIndex = 0; cStateIndex < 25; cStateIndex++ ) {
+ if ( ( g_cCurrentJTAGState == g_JTAGTransistions[ cStateIndex ].CurState ) && ( cNextJTAGState == g_JTAGTransistions[cStateIndex].NextState ) ) {
+ found = 1;
+ break;
+ }
+ }
+ if(found)
+ {
+ g_cCurrentJTAGState = cNextJTAGState;
+ for ( cPathIndex = 0; cPathIndex < g_JTAGTransistions[ cStateIndex ].Pulses; cPathIndex++ ) {
+ if ( ( g_JTAGTransistions[ cStateIndex ].Pattern << cPathIndex ) & 0x80 ) {
+ writePort( g_ucPinTMS, ( unsigned char ) 0x01 );
+ }
+ else {
+ writePort( g_ucPinTMS, ( unsigned char ) 0x00 );
+ }
+ sclock();
+ }
+
+ writePort( g_ucPinTDI, 0x00 );
+ writePort( g_ucPinTMS, 0x00 );
+ }
+}
+
+/***************************************************************
+ *
+ * ispVMStart
+ *
+ * Enable the port to the device and set the state to RESET (TLR).
+ *
+ ***************************************************************/
+
+void ispVMStart()
+{
+#ifdef VME_DEBUG
+ printf( "// ISPVM EMBEDDED ADDED\n" );
+ printf( "STATE RESET;\n" );
+#endif
+
+ ispVMStateMachine( RESET ); /*step devices to RESET state*/
+}
+
+/***************************************************************
+ *
+ * ispVMEnd
+ *
+ * Set the state of devices to RESET to enable the devices and disable
+ * the port.
+ *
+ ***************************************************************/
+
+void ispVMEnd()
+{
+#ifdef VME_DEBUG
+ printf( "// ISPVM EMBEDDED ADDED\n" );
+ printf( "STATE RESET;\n" );
+ printf( "RUNTEST 1.00E-001 SEC;\n" );
+#endif
+
+ ispVMStateMachine( RESET ); /*step devices to RESET state */
+ ispVMDelay( 0x8001 ); /*wake up devices*/
+}
+
+/***************************************************************
+ *
+ * ispVMSend
+ *
+ * Send the TDI data stream to devices. The data stream can be
+ * instructions or data.
+ *
+ ***************************************************************/
+
+signed char ispVMSend( unsigned short a_usiDataSize )
+{
+ //09/11/07 NN added local variables initialization
+ unsigned short iIndex = 0;
+ unsigned short iInDataIndex = 0;
+ unsigned char cCurByte = 0;
+ unsigned char cBitState = 0;
+
+ for ( iIndex = 0; iIndex < a_usiDataSize - 1; iIndex++ ) {
+ if ( iIndex % 8 == 0 ) {
+ cCurByte = g_pucInData[ iInDataIndex++ ];
+ }
+ cBitState = ( unsigned char ) ( ( ( cCurByte << iIndex % 8 ) & 0x80 ) ? 0x01 : 0x00 );
+ writePort( g_ucPinTDI, cBitState );
+ sclock();
+ }
+
+ if ( iIndex % 8 == 0 ) {
+ /* Take care of the last bit */
+ cCurByte = g_pucInData[ iInDataIndex ];
+ }
+
+ cBitState = ( unsigned char ) ( ( ( cCurByte << iIndex % 8 ) & 0x80 ) ? 0x01 : 0x00 );
+
+ writePort( g_ucPinTDI, cBitState );
+ if ( g_usFlowControl & CASCADE ) {
+ /* 1/15/04 Clock in last bit for the first n-1 cascaded frames */
+ sclock();
+ }
+
+ return 0;
+}
+
+/***************************************************************
+ *
+ * ispVMRead
+ *
+ * Read the data stream from devices and verify.
+ *
+ ***************************************************************/
+
+signed char ispVMRead( unsigned short a_usiDataSize )
+{
+ //09/11/07 NN added local variables initialization
+ unsigned short usDataSizeIndex = 0;
+ unsigned short usErrorCount = 0;
+ unsigned short usLastBitIndex = 0;
+ unsigned char cDataByte = 0;
+ unsigned char cMaskByte = 0;
+ unsigned char cInDataByte = 0;
+ unsigned char cCurBit = 0;
+ unsigned char cByteIndex = 0;
+ unsigned short usBufferIndex = 0;
+ unsigned char ucDisplayByte = 0x00;
+ unsigned char ucDisplayFlag = 0x01;
+ char StrChecksum[256] = {0};
+ unsigned char g_usCalculateChecksum = 0x00;
+
+ //09/11/07 NN Type cast mismatch variables
+ usLastBitIndex = (unsigned short)(a_usiDataSize - 1);
+
+#ifndef VME_DEBUG
+ /****************************************************************************
+ *
+ * If mask is not all zeros, then set the display flag to 0x00, otherwise
+ * it shall be set to 0x01 to indicate that data read from the device shall
+ * be displayed. If VME_DEBUG is defined, always display data.
+ *
+ *****************************************************************************/
+
+ for ( usDataSizeIndex = 0; usDataSizeIndex < ( a_usiDataSize + 7 ) / 8; usDataSizeIndex++ ) {
+ if ( g_usDataType & MASK_DATA ) {
+ if ( g_pucOutMaskData[ usDataSizeIndex ] != 0x00 ) {
+ ucDisplayFlag = 0x00;
+ break;
+ }
+ }
+ else if ( g_usDataType & CMASK_DATA ) {
+ g_usCalculateChecksum = 0x01;
+ ucDisplayFlag = 0x00;
+ break;
+ }
+ else {
+ ucDisplayFlag = 0x00;
+ break;
+ }
+ }
+#endif //VME_DEBUG
+
+ /****************************************************************************
+ *
+ * Begin shifting data in and out of the device.
+ *
+ *****************************************************************************/
+
+ for ( usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize; usDataSizeIndex++ ) {
+ if ( cByteIndex == 0 ) {
+
+ /***************************************************************
+ *
+ * Grab byte from TDO buffer.
+ *
+ ***************************************************************/
+
+ if ( g_usDataType & TDO_DATA ) {
+ cDataByte = g_pucOutData[ usBufferIndex ];
+ }
+
+ /***************************************************************
+ *
+ * Grab byte from MASK buffer.
+ *
+ ***************************************************************/
+
+ if ( g_usDataType & MASK_DATA ) {
+ cMaskByte = g_pucOutMaskData[ usBufferIndex ];
+ }
+ else {
+ cMaskByte = 0xFF;
+ }
+
+ /***************************************************************
+ *
+ * Grab byte from CMASK buffer.
+ *
+ ***************************************************************/
+
+ if ( g_usDataType & CMASK_DATA ) {
+ cMaskByte = 0x00;
+ g_usCalculateChecksum = 0x01;
+ }
+
+ /***************************************************************
+ *
+ * Grab byte from TDI buffer.
+ *
+ ***************************************************************/
+
+ if ( g_usDataType & TDI_DATA ) {
+ cInDataByte = g_pucInData[ usBufferIndex ];
+ }
+
+ usBufferIndex++;
+ }
+
+ cCurBit = readPort();
+
+ if ( ucDisplayFlag ) {
+ ucDisplayByte <<= 1;
+ ucDisplayByte |= cCurBit;
+ }
+
+ /****************************************************************************
+ *
+ * Check if data read from port matches with expected TDO.
+ *
+ *****************************************************************************/
+
+ if ( g_usDataType & TDO_DATA ) {
+ //08/28/08 NN Added Calculate checksum support.
+ if( g_usCalculateChecksum )
+ {
+ if(cCurBit == 0x01)
+ g_usChecksum += (1 << (g_uiChecksumIndex % 8));
+ g_uiChecksumIndex++;
+ }
+ else
+ {
+ if ( ( ( ( cMaskByte << cByteIndex ) & 0x80 ) ? 0x01 : 0x00 ) ) {
+ if ( cCurBit != ( unsigned char ) ( ( ( cDataByte << cByteIndex ) & 0x80 ) ? 0x01 : 0x00 ) ) {
+ usErrorCount++;
+ }
+ }
+ }
+ }
+
+ /****************************************************************************
+ *
+ * Write TDI data to the port.
+ *
+ *****************************************************************************/
+
+ writePort( g_ucPinTDI, ( unsigned char ) ( ( ( cInDataByte << cByteIndex ) & 0x80 ) ? 0x01 : 0x00 ) );
+
+ if ( usDataSizeIndex < usLastBitIndex ) {
+
+ /****************************************************************************
+ *
+ * Clock data out from the data shift register.
+ *
+ *****************************************************************************/
+
+ sclock();
+ }
+ else if ( g_usFlowControl & CASCADE ) {
+
+ /****************************************************************************
+ *
+ * Clock in last bit for the first N - 1 cascaded frames.
+ *
+ *****************************************************************************/
+
+ sclock();
+ }
+
+ /***************************************************************
+ *
+ * Increment the byte index. If it exceeds 7, then reset it back
+ * to zero.
+ *
+ ***************************************************************/
+
+ cByteIndex++;
+ if ( cByteIndex >= 8 ) {
+ if ( ucDisplayFlag ) {
+
+ /***************************************************************
+ *
+ * Store displayed data in the TDO buffer. By reusing the TDO
+ * buffer to store displayed data, there is no need to allocate
+ * a buffer simply to hold display data. This will not cause any
+ * false verification errors because the true TDO byte has already
+ * been consumed.
+ *
+ ***************************************************************/
+
+ g_pucOutData[ usBufferIndex - 1 ] = ucDisplayByte;
+ ucDisplayByte = 0;
+ }
+
+ cByteIndex = 0;
+ }
+ //09/12/07 Nguyen changed to display the 1 bit expected data
+ else if(a_usiDataSize == 1)
+ {
+ if ( ucDisplayFlag ) {
+
+ /***************************************************************
+ *
+ * Store displayed data in the TDO buffer. By reusing the TDO
+ * buffer to store displayed data, there is no need to allocate
+ * a buffer simply to hold display data. This will not cause any
+ * false verification errors because the true TDO byte has already
+ * been consumed.
+ *
+ ***************************************************************/
+
+ /****************************************************************************
+ *
+ * Flip ucDisplayByte and store it in cDataByte.
+ *
+ *****************************************************************************/
+ cDataByte = 0x00;
+ for ( usBufferIndex = 0; usBufferIndex < 8; usBufferIndex++ ) {
+ cDataByte <<= 1;
+ if ( ucDisplayByte & 0x01 ) {
+ cDataByte |= 0x01;
+ }
+ ucDisplayByte >>= 1;
+ }
+ g_pucOutData[ 0 ] = cDataByte;
+ ucDisplayByte = 0;
+ }
+
+ cByteIndex = 0;
+ }
+ }
+ if ( ucDisplayFlag ) {
+
+ /****************************************************************************
+ *
+ * Display data read from the device.
+ *
+ *****************************************************************************/
+
+#ifdef VME_DEBUG
+ printf( "RECIEVED TDO (" );
+#else
+ vme_out_string( "Display Data: 0x" );
+#endif //VME_DEBUG
+
+ //09/11/07 NN Type cast mismatch variables
+ for ( usDataSizeIndex = (unsigned short)( ( a_usiDataSize + 7 ) / 8 ); usDataSizeIndex > 0 ; usDataSizeIndex-- ) {
+ cMaskByte = g_pucOutData[ usDataSizeIndex - 1 ];
+ cDataByte = 0x00;
+
+ /****************************************************************************
+ *
+ * Flip cMaskByte and store it in cDataByte.
+ *
+ *****************************************************************************/
+
+ for ( usBufferIndex = 0; usBufferIndex < 8; usBufferIndex++ ) {
+ cDataByte <<= 1;
+ if ( cMaskByte & 0x01 ) {
+ cDataByte |= 0x01;
+ }
+ cMaskByte >>= 1;
+ }
+#ifdef VME_DEBUG
+ printf( "%.2X", cDataByte );
+ if ( ( ( ( a_usiDataSize + 7 ) / 8 ) - usDataSizeIndex ) % 40 == 39 ) {
+ printf( "\n\t\t" );
+ }
+#else
+ vme_out_hex( cDataByte );
+#endif //VME_DEBUG
+ }
+
+#ifdef VME_DEBUG
+ printf( ")\n\n" );
+#else
+ vme_out_string( "\n\n" );
+#endif //VME_DEBUG
+ //09/02/08 Nguyen changed to display the data Checksum
+ if(g_usChecksum != 0)
+ {
+ g_usChecksum &= 0xFFFF;
+ sprintf(StrChecksum,"Data Checksum: %04lx\n\n",g_usChecksum);
+ vme_out_string(StrChecksum);
+ g_usChecksum = 0;
+ }
+ }
+
+ if ( usErrorCount > 0 ) {
+ if ( g_usFlowControl & VERIFYUES ) {
+ vme_out_string( "USERCODE verification failed. Continue programming......\n\n" );
+ g_usFlowControl &= ~( VERIFYUES );
+ return 0;
+ }
+ else {
+
+#ifdef VME_DEBUG
+ printf( "TOTAL ERRORS: %d\n", usErrorCount );
+#endif //VME_DEBUG
+
+ return VME_VERIFICATION_FAILURE;
+ }
+ }
+ else {
+ if ( g_usFlowControl & VERIFYUES ) {
+ vme_out_string( "USERCODE verification passed. Programming aborted. \n\n" );
+ g_usFlowControl &= ~( VERIFYUES );
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+}
+
+/***************************************************************
+ *
+ * ispVMReadandSave
+ *
+ * Support dynamic I/O.
+ *
+ ***************************************************************/
+
+signed char ispVMReadandSave( unsigned short int a_usiDataSize )
+{
+ //09/11/07 NN added local variables initialization
+ unsigned short int usDataSizeIndex = 0;
+ unsigned short int usLastBitIndex = 0;
+ unsigned short int usBufferIndex = 0;
+ unsigned short int usOutBitIndex = 0;
+ unsigned short int usLVDSIndex = 0;
+ unsigned char cDataByte = 0;
+ unsigned char cDMASKByte = 0;
+ unsigned char cInDataByte = 0;
+ unsigned char cCurBit = 0;
+ unsigned char cByteIndex = 0;
+ signed char cLVDSByteIndex = 0;
+
+ //09/11/07 NN Type cast mismatch variables
+ usLastBitIndex = (unsigned short) (a_usiDataSize - 1);
+
+ /***************************************************************
+ *
+ * Iterate through the data bits.
+ *
+ ***************************************************************/
+
+ for ( usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize; usDataSizeIndex++ ) {
+ if ( cByteIndex == 0 ) {
+
+ /***************************************************************
+ *
+ * Grab byte from DMASK buffer.
+ *
+ ***************************************************************/
+
+ if ( g_usDataType & DMASK_DATA ) {
+ cDMASKByte = g_pucOutDMaskData[ usBufferIndex ];
+ }
+ else {
+ cDMASKByte = 0x00;
+ }
+
+ /***************************************************************
+ *
+ * Grab byte from TDI buffer.
+ *
+ ***************************************************************/
+
+ if ( g_usDataType & TDI_DATA ) {
+ cInDataByte = g_pucInData[ usBufferIndex ];
+ }
+
+ usBufferIndex++;
+ }
+
+ cCurBit = readPort();
+ cDataByte = ( unsigned char ) ( ( ( cInDataByte << cByteIndex ) & 0x80 ) ? 0x01 : 0x00 );
+
+ /***************************************************************
+ *
+ * Initialize the byte to be zero.
+ *
+ ***************************************************************/
+
+ if ( usOutBitIndex % 8 == 0 ) {
+ g_pucOutData[ usOutBitIndex / 8 ] = 0x00;
+ }
+
+ /***************************************************************
+ *
+ * Use TDI, DMASK, and device TDO to create new TDI (actually
+ * stored in g_pucOutData).
+ *
+ ***************************************************************/
+
+ if ( ( ( ( cDMASKByte << cByteIndex ) & 0x80 ) ? 0x01 : 0x00 ) ) {
+
+ if ( g_pLVDSList ) {
+ for ( usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; usLVDSIndex++ ) {
+ if ( g_pLVDSList[ usLVDSIndex ].usNegativeIndex == usDataSizeIndex ) {
+ g_pLVDSList[ usLVDSIndex ].ucUpdate = 0x01;
+ break;
+ }
+ }
+ }
+
+ /***************************************************************
+ *
+ * DMASK bit is 1, use TDI.
+ *
+ ***************************************************************/
+
+ g_pucOutData[ usOutBitIndex / 8 ] |= ( unsigned char ) ( ( ( cDataByte & 0x1 ) ? 0x01 : 0x00 ) << ( 7 - usOutBitIndex % 8 ) );
+ }
+ else {
+
+ /***************************************************************
+ *
+ * DMASK bit is 0, use device TDO.
+ *
+ ***************************************************************/
+
+ g_pucOutData[ usOutBitIndex / 8 ] |= ( unsigned char ) ( ( ( cCurBit & 0x1 ) ? 0x01 : 0x00 ) << ( 7 - usOutBitIndex % 8 ) );
+ }
+
+ /***************************************************************
+ *
+ * Shift in TDI in order to get TDO out.
+ *
+ ***************************************************************/
+
+ usOutBitIndex++;
+ writePort( g_ucPinTDI, cDataByte );
+ if ( usDataSizeIndex < usLastBitIndex ) {
+ sclock();
+ }
+
+ /***************************************************************
+ *
+ * Increment the byte index. If it exceeds 7, then reset it back
+ * to zero.
+ *
+ ***************************************************************/
+
+ cByteIndex++;
+ if ( cByteIndex >= 8 ) {
+ cByteIndex = 0;
+ }
+ }
+
+ /***************************************************************
+ *
+ * If g_pLVDSList exists and pairs need updating, then update
+ * the negative-pair to receive the flipped positive-pair value.
+ *
+ ***************************************************************/
+
+ if ( g_pLVDSList ) {
+ for ( usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; usLVDSIndex++ ) {
+ if ( g_pLVDSList[ usLVDSIndex ].ucUpdate ) {
+
+ /***************************************************************
+ *
+ * Read the positive value and flip it.
+ *
+ ***************************************************************/
+
+ cDataByte = ( unsigned char ) ( ( ( g_pucOutData[ g_pLVDSList[ usLVDSIndex ].usPositiveIndex / 8 ] << ( g_pLVDSList[ usLVDSIndex ].usPositiveIndex % 8 ) ) & 0x80 ) ? 0x01 : 0x00 );
+ //09/11/07 NN Type cast mismatch variables
+ cDataByte = ( unsigned char ) (!cDataByte);
+
+ /***************************************************************
+ *
+ * Get the byte that needs modification.
+ *
+ ***************************************************************/
+
+ cInDataByte = g_pucOutData[ g_pLVDSList[ usLVDSIndex ].usNegativeIndex / 8 ];
+
+ if ( cDataByte ) {
+
+ /***************************************************************
+ *
+ * Copy over the current byte and set the negative bit to 1.
+ *
+ ***************************************************************/
+
+ cDataByte = 0x00;
+ for ( cLVDSByteIndex = 7; cLVDSByteIndex >= 0; cLVDSByteIndex-- ) {
+ cDataByte <<= 1;
+ if ( 7 - ( g_pLVDSList[ usLVDSIndex ].usNegativeIndex % 8 ) == cLVDSByteIndex ) {
+
+ /***************************************************************
+ *
+ * Set negative bit to 1.
+ *
+ ***************************************************************/
+
+ cDataByte |= 0x01;
+ }
+ else if ( cInDataByte & 0x80 ) {
+ cDataByte |= 0x01;
+ }
+
+ cInDataByte <<= 1;
+ }
+
+ /***************************************************************
+ *
+ * Store the modified byte.
+ *
+ ***************************************************************/
+
+ g_pucOutData[ g_pLVDSList[ usLVDSIndex ].usNegativeIndex / 8 ] = cDataByte;
+ }
+ else {
+
+ /***************************************************************
+ *
+ * Copy over the current byte and set the negative bit to 0.
+ *
+ ***************************************************************/
+
+ cDataByte = 0x00;
+ for ( cLVDSByteIndex = 7; cLVDSByteIndex >= 0; cLVDSByteIndex-- ) {
+ cDataByte <<= 1;
+ if ( 7 - ( g_pLVDSList[ usLVDSIndex ].usNegativeIndex % 8 ) == cLVDSByteIndex ) {
+
+ /***************************************************************
+ *
+ * Set negative bit to 0.
+ *
+ ***************************************************************/
+
+ cDataByte |= 0x00;
+ }
+ else if ( cInDataByte & 0x80 ) {
+ cDataByte |= 0x01;
+ }
+
+ cInDataByte <<= 1;
+ }
+
+ /***************************************************************
+ *
+ * Store the modified byte.
+ *
+ ***************************************************************/
+
+ g_pucOutData[ g_pLVDSList[ usLVDSIndex ].usNegativeIndex / 8 ] = cDataByte;
+ }
+
+ break;
+ }
+ }
+ }
+
+ return( 0 );
+}
+
+signed char ispVMProcessLVDS( unsigned short a_usLVDSCount )
+{
+ unsigned short usLVDSIndex = 0;
+
+ /***************************************************************
+ *
+ * Allocate memory to hold LVDS pairs.
+ *
+ ***************************************************************/
+
+ ispVMMemManager( LVDS, a_usLVDSCount );
+ g_usLVDSPairCount = a_usLVDSCount;
+
+#ifdef VME_DEBUG
+ printf( "LVDS %d (", a_usLVDSCount );
+#endif //VME_DEBUG
+
+ /***************************************************************
+ *
+ * Iterate through each given LVDS pair.
+ *
+ ***************************************************************/
+
+ for ( usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; usLVDSIndex++ ) {
+
+ /***************************************************************
+ *
+ * Assign the positive and negative indices of the LVDS pair.
+ *
+ ***************************************************************/
+
+ //09/11/07 NN Type cast mismatch variables
+ g_pLVDSList[ usLVDSIndex ].usPositiveIndex = (unsigned short) ispVMDataSize();
+ //09/11/07 NN Type cast mismatch variables
+ g_pLVDSList[ usLVDSIndex ].usNegativeIndex = (unsigned short)ispVMDataSize();
+
+#ifdef VME_DEBUG
+ if ( usLVDSIndex < g_usLVDSPairCount - 1 ) {
+ printf( "%d:%d, ", g_pLVDSList[ usLVDSIndex ].usPositiveIndex, g_pLVDSList[ usLVDSIndex ].usNegativeIndex );
+ }
+ else {
+ printf( "%d:%d", g_pLVDSList[ usLVDSIndex ].usPositiveIndex, g_pLVDSList[ usLVDSIndex ].usNegativeIndex );
+ }
+#endif //VME_DEBUG
+
+ }
+
+#ifdef VME_DEBUG
+ printf( ");\n", a_usLVDSCount );
+#endif //VME_DEBUG
+
+ return( 0 );
+}
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/origi_ispvm_ui.c b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/origi_ispvm_ui.c
new file mode 100644
index 000000000000..112633de87c6
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/origi_ispvm_ui.c
@@ -0,0 +1,908 @@
+/**************************************************************
+*
+* Lattice Semiconductor Corp. Copyright 2008
+*
+* ispVME Embedded allows programming of Lattice's suite of FPGA
+* devices on embedded systems through the JTAG port. The software
+* is distributed in source code form and is open to re - distribution
+* and modification where applicable.
+*
+* ispVME Embedded C Source comprised with 3 modules:
+* ispvm_ui.c is the module provides input and output support.
+* ivm_core.c is the module interpret the VME file(s).
+* hardware.c is the module access the JTAG port of the device(s).
+*
+* The optional module cable.c is for supporting Lattice's parallel
+* port ispDOWNLOAD cable on DOS and Windows 95/98 O/S. It can be
+* requested from Lattice's ispVMSupport.
+*
+***************************************************************/
+
+
+/**************************************************************
+*
+* Revision History of ispvm_ui.c
+*
+* 3/6/07 ht Added functions vme_out_char(),vme_out_hex(),
+* vme_out_string() to provide output resources.
+* Consolidate all printf() calls into the added output
+* functions.
+*
+* 09/11/07 NN Added Global variables initialization
+* 09/24/07 NN Added a switch allowing users to do calibration.
+* Calibration will help to determine the system clock frequency
+* and the count value for one micro-second delay of the target
+* specific hardware.
+* Removed Delay Percent support
+* 11/15/07 NN moved the checking of the File CRC to the end of processing
+* 08/28/08 NN Added Calculate checksum support.
+***************************************************************/
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "vmopcode.h"
+
+/***************************************************************
+*
+* File pointer to the VME file.
+*
+***************************************************************/
+
+FILE * g_pVMEFile = NULL;
+
+#define VME_DEBUG
+
+#define DEBUG
+#ifdef DEBUG
+#define Debug_printf(fmt, args...) printf(fmt, ##args);
+#else
+#define Debug_printf(fmt, args...)
+#endif
+
+/***************************************************************
+*
+* Functions declared in this ispvm_ui.c module
+*
+***************************************************************/
+unsigned char GetByte(void);
+void vme_out_char(unsigned char charOut);
+void vme_out_hex(unsigned char hexOut);
+void vme_out_string(char *stringOut);
+void ispVMMemManager( signed char cTarget, unsigned short usSize );
+void ispVMFreeMem(void);
+void error_handler( short a_siRetCode, char * pszMessage );
+signed char ispVM( const char * a_pszFilename );
+long isp_vme_file_size_get(void);
+int isp_vme_file_size_set(char *file_name);
+int isp_print_progess_bar(long pec);
+void print_usage(char *app_name);
+/***************************************************************
+*
+* Global variables.
+*
+***************************************************************/
+unsigned short g_usPreviousSize = 0;
+unsigned short g_usExpectedCRC = 0;
+static unsigned long vme_file_size = 0;
+
+/***************************************************************
+*
+* External variables and functions declared in ivm_core.c module.
+*
+***************************************************************/
+extern signed char ispVMCode();
+extern void ispVMCalculateCRC32( unsigned char a_ucData );
+extern void ispVMStart();
+extern void ispVMEnd();
+extern unsigned short g_usCalculatedCRC;
+extern unsigned short g_usDataType;
+extern unsigned char * g_pucOutMaskData,
+ * g_pucInData,
+ * g_pucOutData,
+ * g_pucHIRData,
+ * g_pucTIRData,
+ * g_pucHDRData,
+ * g_pucTDRData,
+ * g_pucOutDMaskData,
+ * g_pucIntelBuffer;
+extern unsigned char * g_pucHeapMemory;
+extern unsigned short g_iHeapCounter;
+extern unsigned short g_iHEAPSize;
+extern unsigned short g_usIntelDataIndex;
+extern unsigned short g_usIntelBufferSize;
+extern LVDSPair * g_pLVDSList;
+//08/28/08 NN Added Calculate checksum support.
+extern unsigned long g_usChecksum;
+extern unsigned int g_uiChecksumIndex;
+/***************************************************************
+*
+* External variables and functions declared in hardware.c module.
+*
+***************************************************************/
+extern void calibration(void);
+extern void writePort( unsigned long a_ucPins, unsigned char a_ucValue );
+extern unsigned short g_usCpu_Frequency;
+extern unsigned long g_ucInPort;
+extern unsigned long g_ucOutPort;
+
+/***************************************************************
+*
+* Supported VME versions.
+*
+***************************************************************/
+
+const char * const g_szSupportedVersions[] = { "__VME2.0", "__VME3.0", "____12.0", "____12.1", 0 };
+
+
+/***************************************************************
+*
+* GetByte
+*
+* Returns a byte to the caller. The returned byte depends on the
+* g_usDataType register. If the HEAP_IN bit is set, then the byte
+* is returned from the HEAP. If the LHEAP_IN bit is set, then
+* the byte is returned from the intelligent buffer. Otherwise,
+* the byte is returned directly from the VME file.
+*
+***************************************************************/
+
+unsigned char GetByte()
+{
+ unsigned char ucData = 0;
+ /* Prepare progress bar calculation */
+ static long offset = 0;
+ int pec = 0;
+ long file_size = isp_vme_file_size_get();
+ int bytes_pec = (file_size + 99) / 100;
+
+ if ( g_usDataType & HEAP_IN ) {
+
+ /***************************************************************
+ *
+ * Get data from repeat buffer.
+ *
+ ***************************************************************/
+
+ if ( g_iHeapCounter > g_iHEAPSize ) {
+
+ /***************************************************************
+ *
+ * Data over-run.
+ *
+ ***************************************************************/
+
+ return 0xFF;
+ }
+
+ ucData = g_pucHeapMemory[ g_iHeapCounter++ ];
+ }
+ else if ( g_usDataType & LHEAP_IN ) {
+
+ /***************************************************************
+ *
+ * Get data from intel buffer.
+ *
+ ***************************************************************/
+
+ if ( g_usIntelDataIndex >= g_usIntelBufferSize ) {
+
+ /***************************************************************
+ *
+ * Data over-run.
+ *
+ ***************************************************************/
+
+ return 0xFF;
+ }
+
+ ucData = g_pucIntelBuffer[ g_usIntelDataIndex++ ];
+ }
+ else {
+
+ /***************************************************************
+ *
+ * Get data from file.
+ *
+ ***************************************************************/
+
+ ucData = (unsigned char)fgetc( g_pVMEFile );
+ /* Update the progress bar */
+ pec = ++offset / bytes_pec;
+ if(offset <= (pec * bytes_pec))
+ isp_print_progess_bar(pec);
+ else if(offset >= (file_size - 2))
+ isp_print_progess_bar(100);
+ if ( feof( g_pVMEFile ) ) {
+
+ /***************************************************************
+ *
+ * Reached EOF.
+ *
+ ***************************************************************/
+
+ return 0xFF;
+ }
+ /***************************************************************
+ *
+ * Calculate the 32-bit CRC if the expected CRC exist.
+ *
+ ***************************************************************/
+ if( g_usExpectedCRC != 0)
+ {
+ ispVMCalculateCRC32(ucData);
+ }
+ }
+
+ return ( ucData );
+}
+
+/***************************************************************
+*
+* vme_out_char
+*
+* Send a character out to the output resource if available.
+* The monitor is the default output resource.
+*
+*
+***************************************************************/
+void vme_out_char(unsigned char charOut)
+{
+ printf("%c",charOut);
+}
+/***************************************************************
+*
+* vme_out_hex
+*
+* Send a character out as in hex format to the output resource
+* if available. The monitor is the default output resource.
+*
+*
+***************************************************************/
+void vme_out_hex(unsigned char hexOut)
+{
+ printf("%.2X",hexOut);
+}
+/***************************************************************
+*
+* vme_out_string
+*
+* Send a text string out to the output resource if available.
+* The monitor is the default output resource.
+*
+*
+***************************************************************/
+void vme_out_string(char *stringOut)
+{
+ if(stringOut)
+ {
+ printf("%s",stringOut);
+ }
+
+}
+/***************************************************************
+*
+* ispVMMemManager
+*
+* Allocate memory based on cTarget. The memory size is specified
+* by usSize.
+*
+***************************************************************/
+
+void ispVMMemManager( signed char cTarget, unsigned short usSize )
+{
+ switch ( cTarget ) {
+ case XTDI:
+ case TDI:
+ if ( g_pucInData != NULL ) {
+ if ( g_usPreviousSize == usSize ) {/*memory exist*/
+ break;
+ }
+ else {
+ free( g_pucInData );
+ g_pucInData = NULL;
+ }
+ }
+ g_pucInData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ g_usPreviousSize = usSize;
+ /* FALLTHRU */
+ case XTDO:
+ case TDO:
+ if ( g_pucOutData!= NULL ) {
+ if ( g_usPreviousSize == usSize ) { /*already exist*/
+ break;
+ }
+ else {
+ free( g_pucOutData );
+ g_pucOutData = NULL;
+ }
+ }
+ g_pucOutData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ g_usPreviousSize = usSize;
+ break;
+ case MASK:
+ if ( g_pucOutMaskData != NULL ) {
+ if ( g_usPreviousSize == usSize ) {/*already allocated*/
+ break;
+ }
+ else {
+ free( g_pucOutMaskData );
+ g_pucOutMaskData = NULL;
+ }
+ }
+ g_pucOutMaskData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ g_usPreviousSize = usSize;
+ break;
+ case HIR:
+ if ( g_pucHIRData != NULL ) {
+ free( g_pucHIRData );
+ g_pucHIRData = NULL;
+ }
+ g_pucHIRData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ break;
+ case TIR:
+ if ( g_pucTIRData != NULL ) {
+ free( g_pucTIRData );
+ g_pucTIRData = NULL;
+ }
+ g_pucTIRData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ break;
+ case HDR:
+ if ( g_pucHDRData != NULL ) {
+ free( g_pucHDRData );
+ g_pucHDRData = NULL;
+ }
+ g_pucHDRData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ break;
+ case TDR:
+ if ( g_pucTDRData != NULL ) {
+ free( g_pucTDRData );
+ g_pucTDRData = NULL;
+ }
+ g_pucTDRData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ break;
+ case HEAP:
+ if ( g_pucHeapMemory != NULL ) {
+ free( g_pucHeapMemory );
+ g_pucHeapMemory = NULL;
+ }
+ g_pucHeapMemory = ( unsigned char * ) malloc( usSize + 2 );
+ break;
+ case DMASK:
+ if ( g_pucOutDMaskData != NULL ) {
+ if ( g_usPreviousSize == usSize ) { /*already allocated*/
+ break;
+ }
+ else {
+ free( g_pucOutDMaskData );
+ g_pucOutDMaskData = NULL;
+ }
+ }
+ g_pucOutDMaskData = ( unsigned char * ) malloc( usSize / 8 + 2 );
+ g_usPreviousSize = usSize;
+ break;
+ case LHEAP:
+ if ( g_pucIntelBuffer != NULL ) {
+ free( g_pucIntelBuffer );
+ g_pucIntelBuffer = NULL;
+ }
+ g_pucIntelBuffer = ( unsigned char * ) malloc( usSize + 2 );
+ break;
+ case LVDS:
+ if ( g_pLVDSList != NULL ) {
+ free( g_pLVDSList );
+ g_pLVDSList = NULL;
+ }
+ g_pLVDSList = ( LVDSPair * ) calloc( usSize, sizeof( LVDSPair ) );
+ break;
+ default:
+ return;
+ }
+}
+
+/***************************************************************
+*
+* ispVMFreeMem
+*
+* Free memory that were dynamically allocated.
+*
+***************************************************************/
+
+void ispVMFreeMem()
+{
+ if ( g_pucHeapMemory != NULL ) {
+ free( g_pucHeapMemory );
+ g_pucHeapMemory = NULL;
+ }
+
+ if ( g_pucOutMaskData != NULL ) {
+ free( g_pucOutMaskData );
+ g_pucOutMaskData = NULL;
+ }
+
+ if ( g_pucInData != NULL ) {
+ free( g_pucInData );
+ g_pucInData = NULL;
+ }
+
+ if ( g_pucOutData != NULL ) {
+ free( g_pucOutData );
+ g_pucOutData = NULL;
+ }
+
+ if ( g_pucHIRData != NULL ) {
+ free( g_pucHIRData );
+ g_pucHIRData = NULL;
+ }
+
+ if ( g_pucTIRData != NULL ) {
+ free( g_pucTIRData );
+ g_pucTIRData = NULL;
+ }
+
+ if ( g_pucHDRData != NULL ) {
+ free( g_pucHDRData );
+ g_pucHDRData = NULL;
+ }
+
+ if ( g_pucTDRData != NULL ) {
+ free( g_pucTDRData );
+ g_pucTDRData = NULL;
+ }
+
+ if ( g_pucOutDMaskData != NULL ) {
+ free( g_pucOutDMaskData );
+ g_pucOutDMaskData = NULL;
+ }
+
+ if ( g_pucIntelBuffer != NULL ) {
+ free( g_pucIntelBuffer );
+ g_pucIntelBuffer = NULL;
+ }
+
+ if ( g_pLVDSList != NULL ) {
+ free( g_pLVDSList );
+ g_pLVDSList = NULL;
+ }
+}
+
+/***************************************************************
+*
+* error_handler
+*
+* Reports the error message.
+*
+***************************************************************/
+
+void error_handler( short a_siRetCode, char * pszMessage )
+{
+ const char * pszErrorMessage[] = { "pass",
+ "verification fail",
+ "can't find the file",
+ "wrong file type",
+ "file error",
+ "option error",
+ "crc verification error" };
+
+ strcpy( pszMessage, pszErrorMessage[ -a_siRetCode ] );
+}
+/***************************************************************
+*
+* ispVM
+*
+* The entry point of the ispVM embedded. If the version and CRC
+* are verified, then the VME will be processed.
+*
+***************************************************************/
+
+signed char ispVM( const char * a_pszFilename )
+{
+ char szFileVersion[ 9 ] = { 0 };
+ signed char cRetCode = 0;
+ signed char cIndex = 0;
+ signed char cVersionIndex = 0;
+ unsigned char ucReadByte = 0;
+
+ /***************************************************************
+ *
+ * Global variables initialization.
+ *
+ * 09/11/07 NN Added
+ ***************************************************************/
+ g_pucHeapMemory = NULL;
+ g_iHeapCounter = 0;
+ g_iHEAPSize = 0;
+ g_usIntelDataIndex = 0;
+ g_usIntelBufferSize = 0;
+ g_usPreviousSize = 0;
+
+ /***************************************************************
+ *
+ * Open a file pointer to the VME file.
+ *
+ ***************************************************************/
+
+ if ( ( g_pVMEFile = fopen( a_pszFilename, "rb" ) ) == NULL ) {
+ return VME_FILE_READ_FAILURE;
+ }
+ g_usCalculatedCRC = 0;
+ g_usExpectedCRC = 0;
+ ucReadByte = GetByte();
+ switch( ucReadByte ) {
+ case FILE_CRC:
+
+ /***************************************************************
+ *
+ * Read and store the expected CRC to do the comparison at the end.
+ * Only versions 3.0 and higher support CRC protection.
+ *
+ ***************************************************************/
+
+ g_usExpectedCRC = (unsigned char ) fgetc( g_pVMEFile );
+ g_usExpectedCRC <<= 8;
+ g_usExpectedCRC |= fgetc( g_pVMEFile );
+
+
+ /***************************************************************
+ *
+ * Read and store the version of the VME file.
+ *
+ ***************************************************************/
+
+ for ( cIndex = 0; cIndex < 8; cIndex++ ) {
+ szFileVersion[ cIndex ] = GetByte();
+ }
+
+ break;
+ default:
+
+ /***************************************************************
+ *
+ * Read and store the version of the VME file. Must be version 2.0.
+ *
+ ***************************************************************/
+
+ szFileVersion[ 0 ] = ( signed char ) ucReadByte;
+ for ( cIndex = 1; cIndex < 8; cIndex++ ) {
+ szFileVersion[ cIndex ] = GetByte();
+ }
+
+ break;
+ }
+
+ /***************************************************************
+ *
+ * Compare the VME file version against the supported version.
+ *
+ ***************************************************************/
+ for ( cVersionIndex = 0; g_szSupportedVersions[ cVersionIndex ] != 0; cVersionIndex++ ) {
+ for ( cIndex = 0; cIndex < 8; cIndex++ ) {
+ if ( szFileVersion[ cIndex ] != g_szSupportedVersions[ cVersionIndex ][ cIndex ] ) {
+ cRetCode = VME_VERSION_FAILURE;
+ break;
+ }
+ cRetCode = 0;
+ }
+
+ if ( cRetCode == 0 ) {
+
+ /***************************************************************
+ *
+ * Found matching version, break.
+ *
+ ***************************************************************/
+
+ break;
+ }
+ }
+
+ if ( cRetCode < 0 ) {
+
+ /***************************************************************
+ *
+ * VME file version failed to match the supported versions.
+ *
+ ***************************************************************/
+
+ fclose( g_pVMEFile );
+ g_pVMEFile = NULL;
+ return VME_VERSION_FAILURE;
+ }
+
+ /***************************************************************
+ *
+ * Enable the JTAG port to communicate with the device.
+ * Set the JTAG state machine to the Test-Logic/Reset State.
+ *
+ ***************************************************************/
+
+ ispVMStart();
+
+ /***************************************************************
+ *
+ * Process the VME file.
+ *
+ ***************************************************************/
+
+ cRetCode = ispVMCode();
+
+ /***************************************************************
+ *
+ * Set the JTAG State Machine to Test-Logic/Reset state then disable
+ * the communication with the JTAG port.
+ *
+ ***************************************************************/
+
+ ispVMEnd();
+
+ fclose( g_pVMEFile );
+ g_pVMEFile = NULL;
+
+
+ ispVMFreeMem();
+
+ /***************************************************************
+ *
+ * Compare the expected CRC versus the calculated CRC.
+ *
+ ***************************************************************/
+
+ if ( cRetCode == 0 && g_usExpectedCRC != 0 && ( g_usExpectedCRC != g_usCalculatedCRC ) ) {
+ printf( "Expected CRC: 0x%.4X\n", g_usExpectedCRC );
+ printf( "Calculated CRC: 0x%.4X\n", g_usCalculatedCRC );
+ return VME_CRC_FAILURE;
+ }
+
+ return ( cRetCode );
+}
+
+// inline char *strlwr(char *str)
+// {
+// char *orig = str;
+
+// for (; *str != '\0'; str++)
+// *str = tolower(*str);
+
+// return orig;
+// }
+
+int isp_vme_file_size_set(char *file_name)
+{
+ struct stat statbuf;
+
+ stat(file_name, &statbuf);
+ vme_file_size = statbuf.st_size;
+
+ return 0;
+}
+
+long isp_vme_file_size_get(void)
+{
+ return vme_file_size;
+}
+
+int isp_print_progess_bar(long pec)
+{
+ int i = 0;
+
+ printf("[");
+ for(i = 0; i < (pec / 2); i++) {
+ printf("=");
+ }
+ for(i = pec / 2; i < 50; i++) {
+ printf(" ");
+ }
+ printf("]");
+ printf(" [%ld%%]\r", pec);
+ fflush(stdout);
+ if(pec == 100)
+ printf("\n");
+
+ return 0;
+}
+
+void print_usage(char *app_name){
+ printf(" usage: %s [options] [filename]\n", app_name);
+ printf(" Options:\n");
+ printf(" -h : to print this message.\n");
+ printf(" -c : to select the JTAG chain 0,1,2\n");
+ printf(" default is at 0.\n");
+ printf(" -f : to specify CPU clock frequency in MHz.\n");
+}
+
+/***************************************************************
+*
+* main
+*
+***************************************************************/
+int main( int argc, char * argv[] )
+{
+ short siRetCode = 0;
+ short sicalibrate = 1;
+ short setCpuFrequency = 0;
+
+ char *cpld_img = "cpld.vme";
+ int JTAG_chain = 0;
+ int option;
+ //08/28/08 NN Added Calculate checksum support.
+ g_usChecksum = 0;
+ g_uiChecksumIndex = 0;
+
+ vme_out_string( " Lattice Semiconductor Corp.\n" );
+ vme_out_string( "\n ispVME(tm) V");
+ vme_out_string( VME_VERSION_NUMBER );
+ vme_out_string(" Copyright 1998-2011.\n");
+ vme_out_string( "\nFor daisy chain programming of all in-system programmable devices\n" );
+ vme_out_string( "\nCLS internal version 1.1.0 for Phalanx, Fishbone48, and Fishbone32.\n\n" );
+
+ while( ( option = getopt(argc, argv, "f:c:h")) != -1 ){
+ switch (option){
+ case 'h':
+ print_usage(argv[0]);
+ return 0;
+ case 'c':
+ // set JTAG chain number
+ JTAG_chain = atoi(optarg);
+ break;
+ case 'f':
+ // set CPU frequency
+ g_usCpu_Frequency = atoi(optarg);
+ setCpuFrequency = 1;
+ break;
+ case '?':
+ print_usage(argv[0]);
+ return -1;
+ }
+ }
+
+ if( argc - optind )
+ cpld_img = argv[optind];
+
+ if( JTAG_chain < 0 || JTAG_chain > 2 ){
+ //print usage and return error
+ printf("Invalid JTAG chain specify: %d\n", JTAG_chain);
+ print_usage(argv[0]);
+ return -1;
+ }
+
+ if( g_usCpu_Frequency <= 0 && setCpuFrequency ){
+ //print usage and return error
+ printf("Invalid CPU frequency specify: %d\n", g_usCpu_Frequency);
+ print_usage(argv[0]);
+ return -1;
+ }
+
+ if (iopl(3))
+ {
+ perror("iopl");
+ exit(1);/* reminder here: do not use "return", I warned */
+ }
+ else
+ {
+
+ /* For Denvertion CPU */
+ // isp_dnv_gpio_init();
+ // isp_dnv_gpio_config(GPIO_TCK_CONFIG, GPIO_DIR_OUTPUT);
+ // isp_dnv_gpio_config(GPIO_TMS_CONFIG, GPIO_DIR_OUTPUT);
+ // isp_dnv_gpio_config(GPIO_TDI_CONFIG, GPIO_DIR_OUTPUT);
+ // isp_dnv_gpio_config(GPIO_TDO_CONFIG, GPIO_DIR_INPUT);
+
+
+ /* TODO: Convert to bit read/write function */
+ // Set ICHx GPIO_USE_SEL of TDI,TDO,TMS,TCK,GPIO14
+ unsigned long data = 0;
+ data = inl_p(GPIO_USE_SEL);
+ data |= (1U << GPIO_TCK_CONFIG);
+ data |= (1U << GPIO_TMS_CONFIG);
+ data |= (1U << GPIO_TDI_CONFIG);
+ data |= (1U << GPIO_TDO_CONFIG);
+ data |= (1U << 14);
+ outl_p(data, GPIO_USE_SEL);
+ // Set ICHx GP_IO_SEL of TDI,TDO,TMS,TCK,GPIO14
+ data = inl_p(GP_IO_SEL);
+ data &= ~(1U << GPIO_TCK_CONFIG);
+ data &= ~(1U << GPIO_TMS_CONFIG);
+ data &= ~(1U << GPIO_TDI_CONFIG);
+ data &= ~(1U << 14);
+ data |= (1U << GPIO_TDO_CONFIG);
+ outl_p(data, GP_IO_SEL);
+
+ // Set ICHx GPIO_USE_SEL of GPIO70
+ data = inl_p(GPIO_USE_SEL3);
+ data |= (1U << 6);
+ outl_p(data, GPIO_USE_SEL3);
+ // Set ICHx GP_IO_SEL of GPIO70
+ data = inl_p(GP_IO_SEL3);
+ data &= ~(1U << 6);
+ outl_p(data, GP_IO_SEL3);
+ }
+
+ /* FIXME: export and setting GPIO register bank on the fly could cause a bug.
+ * Plan to add the function to set/clear GPIO register bit for more sucure.
+ */
+ /* Switch to control JTAG chain muxes */
+ switch (JTAG_chain){
+ case 0:
+ printf("Select main JTAG chain\n");
+ // Set GPIO70 to Low
+ g_ucOutPort = GP_LVL3;
+ writePort( 6, 0x00 );
+ break;
+ case 1:
+ printf("Select Top line card JTAG chain\n");
+ // Ste GPIO70 to High
+ g_ucOutPort = GP_LVL3;
+ writePort( 6, 0x01 );
+ // Ste GPIO14 to Low
+ g_ucOutPort = GP_LVL;
+ writePort( 14, 0x00 );
+ break;
+ case 2:
+ printf("Select Buttom line card JTAG chain\n");
+ // Ste GPIO70 to High
+ g_ucOutPort = GP_LVL3;
+ writePort( 6, 0x01 );
+ // Ste GPIO14 to High
+ g_ucOutPort = GP_LVL;
+ writePort( 14, 0x01 );
+ break;
+ }
+
+ /* FIXME: This line is very important for TDI,TMS,TCK,TDO */
+ // Set the register back to first bank!
+ g_ucOutPort = GP_LVL;
+
+ printf("Set CPU frequency to %d MHz\n", g_usCpu_Frequency);
+
+ siRetCode = 0;
+ if(sicalibrate)
+ {
+ vme_out_string ("calibration ....\n\n");
+ calibration();
+ }
+
+ printf( "Processing virtual machine file (");
+ printf( "%s",cpld_img);
+ printf(")......\n\n");
+ isp_vme_file_size_set(cpld_img);
+ siRetCode = ispVM(cpld_img);
+
+ /* Set JTAG chain muxes to default chain. */
+ // Set GPIO70 to Low
+ g_ucOutPort = GP_LVL3;
+ writePort( 6, 0x00 );
+
+ /* For Denverton CPU */
+ // isp_dnv_gpio_deinit();
+
+ if ( siRetCode < 0 ) {
+ vme_out_string( "Failed due to ");
+ printf( " return code %d\n\n", siRetCode);
+ vme_out_string( "+=======+\n" );
+ vme_out_string( "| FAIL! |\n" );
+ vme_out_string( "+=======+\n\n" );
+ }else {
+ vme_out_string( "+=======+\n" );
+ vme_out_string( "| PASS! |\n" );
+ vme_out_string( "+=======+\n\n" );
+ //08/28/08 NN Added Calculate checksum support.
+ if(g_usChecksum != 0)
+ {
+ g_usChecksum &= 0xFFFF;
+ printf("Data Checksum: %.4lx\n\n",g_usChecksum);
+ g_usChecksum = 0;
+ }
+ }
+
+ if (iopl(0))
+ {
+ perror("iopl");
+ exit(1);/* reminder here: do not use "return", I warned */
+ }
+ exit( siRetCode );
+}
+
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/vmopcode.h b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/vmopcode.h
new file mode 100644
index 000000000000..6b2c94d510f7
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/ispvme_12.2/vmopcode.h
@@ -0,0 +1,233 @@
+/***************************************************************
+*
+* This is the include file for Lattice Semiconductor's ispVM
+* Embedded software application.
+*
+***************************************************************/
+
+/***************************************************************
+*
+* VME version.
+*
+* History:
+*
+***************************************************************/
+#define VME_VERSION_NUMBER "12.2"
+
+/***************************************************************
+*
+* Maximum declarations.
+*
+***************************************************************/
+
+#define VMEHEXMAX 60000L /* The hex file is split 60K per file. */
+#define SCANMAX 64000L /* The maximum SDR/SIR burst. */
+
+/***************************************************************
+*
+* Supported JTAG state transitions.
+*
+***************************************************************/
+
+#define RESET 0x00
+#define IDLE 0x01
+#define IRPAUSE 0x02
+#define DRPAUSE 0x03
+#define SHIFTIR 0x04
+#define SHIFTDR 0x05
+#define DRCAPTURE 0x06
+
+/***************************************************************
+*
+* Flow control register bit definitions. A set bit indicates
+* that the register currently exhibits the corresponding mode.
+*
+***************************************************************/
+
+#define INTEL_PRGM 0x0001 /* Intelligent programming is in effect. */
+#define CASCADE 0x0002 /* Currently splitting large SDR. */
+#define REPEATLOOP 0x0008 /* Currently executing a repeat loop. */
+#define SHIFTRIGHT 0x0080 /* The next data stream needs a right shift. */
+#define SHIFTLEFT 0x0100 /* The next data stream needs a left shift. */
+#define VERIFYUES 0x0200 /* Continue if fail is in effect. */
+
+/***************************************************************
+*
+* DataType register bit definitions. A set bit indicates
+* that the register currently holds the corresponding type of data.
+*
+***************************************************************/
+
+#define EXPRESS 0x0001 /* Simultaneous program and verify. */
+#define SIR_DATA 0x0002 /* SIR is the active SVF command. */
+#define SDR_DATA 0x0004 /* SDR is the active SVF command. */
+#define COMPRESS 0x0008 /* Data is compressed. */
+#define TDI_DATA 0x0010 /* TDI data is present. */
+#define TDO_DATA 0x0020 /* TDO data is present. */
+#define MASK_DATA 0x0040 /* MASK data is present. */
+#define HEAP_IN 0x0080 /* Data is from the heap. */
+#define LHEAP_IN 0x0200 /* Data is from intel data buffer. */
+#define VARIABLE 0x0400 /* Data is from a declared variable. */
+#define CRC_DATA 0x0800 /* CRC data is pressent. */
+#define CMASK_DATA 0x1000 /* CMASK data is pressent. */
+#define RMASK_DATA 0x2000 /* RMASK data is pressent. */
+#define READ_DATA 0x4000 /* READ data is pressent. */
+#define DMASK_DATA 0x8000 /* DMASK data is pressent. */
+
+/***************************************************************
+*
+* Pin opcodes.
+*
+***************************************************************/
+
+#define signalENABLE 0x1C /* ispENABLE pin. */
+#define signalTMS 0x1D /* TMS pin. */
+#define signalTCK 0x1E /* TCK pin. */
+#define signalTDI 0x1F /* TDI pin. */
+#define signalTRST 0x20 /* TRST pin. */
+
+/***************************************************************
+*
+* Supported vendors.
+*
+***************************************************************/
+
+#define VENDOR 0x56
+#define LATTICE 0x01
+#define ALTERA 0x02
+#define XILINX 0x03
+
+/***************************************************************
+*
+* Opcode definitions.
+*
+* Note: opcodes must be unique.
+*
+***************************************************************/
+
+#define ENDDATA 0x00 /* The end of the current SDR data stream. */
+#define RUNTEST 0x01 /* The duration to stay at the stable state. */
+#define ENDDR 0x02 /* The stable state after SDR. */
+#define ENDIR 0x03 /* The stable state after SIR. */
+#define ENDSTATE 0x04 /* The stable state after RUNTEST. */
+#define TRST 0x05 /* Assert the TRST pin. */
+#define HIR 0x06 /* The sum of the IR bits of the leading devices. */
+#define TIR 0x07 /* The sum of the IR bits of the trailing devices. */
+#define HDR 0x08 /* The number of leading devices. */
+#define TDR 0x09 /* The number of trailing devices. */
+#define ispEN 0x0A /* Assert the ispEN pin. */
+#define FREQUENCY 0x0B /* The maximum clock rate to run the JTAG state machine. */
+#define STATE 0x10 /* Move to the next stable state. */
+#define SIR 0x11 /* The instruction stream follows. */
+#define SDR 0x12 /* The data stream follows. */
+#define TDI 0x13 /* The following data stream feeds into the device. */
+#define TDO 0x14 /* The following data stream is compared against the device. */
+#define MASK 0x15 /* The following data stream is used as mask. */
+#define XSDR 0x16 /* The following data stream is for simultaneous program and verify. */
+#define XTDI 0x17 /* The following data stream is for shift in only. It must be stored for the next XSDR. */
+#define XTDO 0x18 /* There is not data stream. The data stream was stored from the previous XTDI. */
+#define MEM 0x19 /* The maximum memory needed to allocate in order hold one row of data. */
+#define WAIT 0x1A /* The duration of delay to observe. */
+#define TCK 0x1B /* The number of TCK pulses. */
+#define SHR 0x23 /* Set the flow control register for right shift. */
+#define SHL 0x24 /* Set the flow control register for left shift. */
+#define HEAP 0x32 /* The memory size needed to hold one loop. */
+#define REPEAT 0x33 /* The beginning of the loop. */
+#define LEFTPAREN 0x35 /* The beginning of data following the loop. */
+#define VAR 0x55 /* Plac holder for loop data. */
+#define SEC 0x1C /* The delay time in seconds that must be observed. */
+#define SMASK 0x1D /* The mask for TDI data. */
+#define MAX 0x1E /* The absolute maximum wait time. */
+#define ON 0x1F /* Assert the targeted pin. */
+#define OFF 0x20 /* Dis-assert the targeted pin. */
+#define SETFLOW 0x30 /* Change the flow control register. */
+#define RESETFLOW 0x31 /* Clear the flow control register. */
+#define CRC 0x47 /* The following data stream is used for CRC calculation. */
+#define CMASK 0x48 /* The following data stream is used as mask for CRC calculation. */
+#define RMASK 0x49 /* The following data stream is used as mask for read and save. */
+#define READ 0x50 /* The following data stream is used for read and save. */
+#define ENDLOOP 0x59 /* The end of the repeat loop. */
+#define SECUREHEAP 0x60 /* Used to secure the HEAP opcode. */
+#define VUES 0x61 /* Support continue if fail. */
+#define DMASK 0x62 /* The following data stream is used for dynamic I/O. */
+#define COMMENT 0x63 /* Support SVF comments in the VME file. */
+#define HEADER 0x64 /* Support header in VME file. */
+#define FILE_CRC 0x65 /* Support crc-protected VME file. */
+#define LCOUNT 0x66 /* Support intelligent programming. */
+#define LDELAY 0x67 /* Support intelligent programming. */
+#define LSDR 0x68 /* Support intelligent programming. */
+#define LHEAP 0x69 /* Memory needed to hold intelligent data buffer */
+#define CONTINUE 0x70 /* Allow continuation. */
+#define LVDS 0x71 /* Support LVDS. */
+#define ENDVME 0x7F /* End of the VME file. */
+#define HIGH 0x80 /* Assert the targeted pin. */
+#define LOW 0x81 /* Dis-assert the targeted pin. */
+#define ENDFILE 0xFF /* End of file. */
+
+/* Denverton GPIO MAPPING */
+#define MAP_MASK (sysconf(_SC_PAGE_SIZE)-1)
+#define MAP_SIZE(addr) ( (addr & MAP_MASK) + 8 )
+#define OFFSET_ADDR(addr) (addr & MAP_MASK)
+#define GET_PORT(addr) ( (addr >> 16) & 0xFF )
+#define DNV_BAR 0xFD000000
+#define DNV_GPIO_TCK_CONFIG 0xFDC20510
+#define DNV_GPIO_TMS_CONFIG 0xFDC20508
+#define DNV_GPIO_TDI_CONFIG 0xFDC204D8
+#define DNV_GPIO_TDO_CONFIG 0xFDC50570
+#define DNV_GPIO_DIR_INPUT 1
+#define DNV_GPIO_DIR_OUTPUT 0
+#define DNV_GPIO_LVL_HIGH 1
+#define DNV_GPIO_LVL_LOW 0
+
+// FIXME: This only works on Fishbone/Phalanx
+#define CPU_FREQ_MH_CONFIG 2200 /* in MHz */
+#define GPIO_USE_SEL 0x500
+#define GP_IO_SEL 0x504
+#define GP_LVL 0x50C
+#define GPIO_USE_SEL2 0x530
+#define GP_IO_SEL2 0x534
+#define GP_LVL2 0x538
+#define GPIO_USE_SEL3 0x540
+#define GP_IO_SEL3 0x544
+#define GP_LVL3 0x548
+
+#define GPIO_TCK_CONFIG 18
+#define GPIO_TMS_CONFIG 9
+#define GPIO_TDI_CONFIG 8
+#define GPIO_TDO_CONFIG 10
+#define GPIO_ENABLE_CONFIG 13 /* GPIO 13 is unused */
+#define GPIO_TRST_CONFIG 13 /* GPIO 13 is unused */
+
+/***************************************************************
+*
+* ispVM Embedded Return Codes.
+*
+***************************************************************/
+
+#define VME_VERIFICATION_FAILURE -1
+#define VME_FILE_READ_FAILURE -2
+#define VME_VERSION_FAILURE -3
+#define VME_INVALID_FILE -4
+#define VME_ARGUMENT_FAILURE -5
+#define VME_CRC_FAILURE -6
+
+
+/***************************************************************
+*
+* Type definitions.
+*
+***************************************************************/
+
+/* Support LVDS */
+typedef struct {
+ unsigned short usPositiveIndex;
+ unsigned short usNegativeIndex;
+ unsigned char ucUpdate;
+} LVDSPair;
+
+void isp_dnv_gpio_config( unsigned int gpio, unsigned int dir );
+void isp_dnv_gpio_write( unsigned int gpio, unsigned int value);
+int isp_dnv_gpio_read( unsigned int gpio);
+
+void isp_dnv_gpio_init(void);
+void isp_dnv_gpio_deinit(void);
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/platformutil.py b/platform/broadcom/sonic-platform-modules-cel/tools/platformutil.py
new file mode 100644
index 000000000000..5c73dd9870f3
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/platformutil.py
@@ -0,0 +1,642 @@
+#!/usr/bin/env python
+#
+# platformutil/main.py
+#
+# Command-line utility for interacting with PSU in SONiC
+#
+# example output
+# platformutil psu status
+# PSU Presence Status PN SN
+# PSU 1 PRESENT OK CSU550AP-3-300 M623TW004ZAAL
+# PSU 2 NOT_PRESENT N/A N/A N/A
+#
+# platformutil fan status
+# FAN Status Speed Low_thd High_thd PN SN
+# FAN 1 OK 10169 RPM 300 RPM 16000 RPM M6510-FAN-F 1000000000014
+# FAN 2 NOT_OK 20000 RPM 300 RPM 16000 RPM M6510-FAN-F 1000000000014
+#
+# platformutil sensor status
+#Sensor InputName State Value Low_thd High_thd
+#----------------- ------------------- ------- -------- --------- ----------
+#syscpld-i2c-0-0d CPU temp NOT_OK 41.0 C 0 C 0.0 C
+#syscpld-i2c-0-0d Optical temp NOT_OK 26.0 C 0 C 0.0 C
+#syscpld-i2c-0-0d Switch temp NOT_OK 35.0 C 0 C 0.0 C
+#
+# should implenmet the below classes in the specified plugin
+#
+# class PsuUtil:
+# int get_num_psus(); //get the number of power supply units
+# bool get_psu_presence(int index) //get the power status of the psu, index:1,2
+# bool get_psu_status(int index) //get the running status of the psu,index:1,2
+# str get_psu_sn(int index) //get the serial number of the psu, return value example: "M623TW004ZAAL"
+# str get_psu_pn(int index) //get the product name of the psu, return value example: "CSU550AP-3-300"
+#
+# // Get all information of PSUs, returns JSON objects in python 'DICT'.
+# // return value of get_all():
+# // Number: mandatory, max number of PSU, integer
+# // PSU1, PSU2, ...: mandatory, PSU name, string
+# // Present: mandatory for each PSU, present status, boolean, True for present, False for NOT present
+# // PowerStatus: conditional, if PRESENT is True, power status of PSU,
+# // boolean, True for powered, False for NOT powered
+# // PN, conditional, if PRESENT is True, PN of the PSU, string
+# // SN, conditional, if PRESENT is True, SN of the PSU, string
+# // example:
+# // {
+# // "Number": 2,
+# // "PSU1": {
+# // "Present": True,
+# // "PowerStatus": True,
+# // "PN": "PN-EXAMPLE-123",
+# // "SN": "SN-EXAMPLE-123",
+# // "InputStatus": True,
+# // "OutputStatus": True,
+# // "InputType": "DC"
+# // "AirFlow": "BTOF"
+# // },
+# // "PSU2": {
+# // "Present": False
+# // }
+# // }
+# dict get_all()
+
+# class FanUtil:
+# int get_fans_name_list(); //get the names of all the fans(FAN1-1,FAN1-2,FAN2-1,FAN2-2...)
+# int get_fan_speed(int index); //get the current speed of the fan, the unit is "RPM"
+# int get_fan_low_threshold(int index); //get the low speed threshold of the fan, if the current speed < low speed threshold, the status of the fan is ok.
+# int get_fan_high_threshold(int index); //get the hight speed threshold of the fan, if the current speed > high speed threshold, the status of the fan is not ok
+# str get_fan_pn(int index);//get the product name of the fan
+# str get_fan_sn(int index);//get the serial number of the fan
+# // Get all information of system FANs, returns JSON objects in python 'DICT'.
+# // Number, mandatory, max number of FAN, integer
+# // FAN1_1, FAN1_2, ... mandatory, FAN name, string
+# // Present, mandatory for each FAN, present status, boolean, True for present, False for NOT present, read directly from h/w
+# // Running, conditional, if PRESENT is True, running status of the FAN, True for running, False for stopped, read directly from h/w
+# // Speed, conditional, if PRESENT is True, real FAN speed, float, read directly from h/w
+# // LowThd, conditional, if PRESENT is True, lower bound of FAN speed, float, read from h/w
+# // HighThd, conditional, if PRESENT is True, upper bound of FAN speed, float, read from h/w
+# // PN, conditional, if PRESENT is True, PN of the FAN, string
+# // SN, conditional, if PRESENT is True, SN of the FAN, string
+# // Return value python 'dict' object example:
+# // {
+# // "Number": 3,
+# // "FAN1_1": {
+# // "Present": True,
+# // "Running": True,
+# // "Speed": 2000.0,
+# // "LowThd": 1000.0,
+# // "HighThd": 15000.0,
+# // "PN": "PN-EXAMPLE-123",
+# // "SN": "SN-EXAMPLE-123"
+# // "Status": True,
+# // "AirFlow": "FTOB"
+# // },
+# // "FAN1_2": {
+# // "Present": True,
+# // "Running": True,
+# // "Speed": 2500.0,
+# // "LowThd": 1000.0,
+# // "HighThd": 15000.0,
+# // "PN": "PN-EXAMPLE-456",
+# // "SN": "SN-EXAMPLE-456"
+# // "Status": True,
+# // "AirFlow": "BTOF"
+# // },
+# // "FAN2_1": {
+# // "Present": True,
+# // "Running": False
+# // },
+# // "FAN2_2": {
+# // "Present": True,
+# // "Running": False
+# // },
+# // "FAN3_1": {
+# // "Present": False
+# // },
+# // "FAN3_2": {
+# // "Present": False
+# // }
+# // }
+# dict get_all()
+#
+# class SensorUtil:
+# int get_num_sensors(); //get the number of sensors
+# int get_sensor_input_num(int index); //get the number of the input items of the specified sensor
+# str get_sensor_name(int index);// get the device name of the specified sensor.for example "coretemp-isa-0000"
+# str get_sensor_input_name(int sensor_index, int input_index); //get the input item name of the specified input item of the specified sensor index, for example "Physical id 0"
+# str get_sensor_input_type(int sensor_index, int input_index); //get the item type of the specified input item of the specified sensor index, the return value should
+# //among "voltage","temperature"...
+# float get_sensor_input_value(int sensor_index, int input_index);//get the current value of the input item, the unit is "V" or "C"...
+# float get_sensor_input_low_threshold(int sensor_index, int input_index); //get the low threshold of the value, the status of this item is not ok if the current
+# //value high_threshold
+# // Get all information of system sensors, returns JSON objects in python 'DICT'.
+# // SensorName1, SensorName2, ... optional, string
+# // SensorInput1, SensorInput2, ... optional, string
+# // Type, mandatory in SensorInput$INDEX, should be on of { "temperature", "voltage", "power", "amp", "RPM" }
+# // Value, mandatory in SensorInput$INDEX, float , real value
+# // LowThd, mandatory in SensorInput$INDEX, float , lower bound of value
+# // HighThd, mandatory in SensorInput$INDEX, float , upper bound of value
+# // Return python 'dict' objects, example:
+# // {
+# // "SensorName1": {
+# // "CPU_TEMP":
+# // "Type": "temperature",
+# // "Value": 37.3,
+# // "LowThd": 0.0,
+# // "HighThd": 110.0
+# // },
+# // "SWITCH_TEMP": {
+# // "Type": "temperature",
+# // "Value": 45.2,
+# // "LowThd": 0.0,
+# // "HighThd": 108.0
+# // },
+# // "INLET_TEMP": {
+# // "Type": "temperature",
+# // "Value": 22.0,
+# // "LowThd": 0.0,
+# // "HighThd": 70.0
+# // },
+# // "Sys_AirFlow": "BTOF",
+# // "Switch_VDDCore_0.8v": {
+# // "Type": "voltage",
+# // "Value": 0.75,
+# // "LowThd": 0.7,
+# // "HighThd": 0.85
+# // },
+# // "Cpu_VDDCore_0.8v": {
+# // "Type": "voltage",
+# // "Value": 0.75,
+# // "LowThd": 0.7,
+# // "HighThd": 0.85
+# // },
+# // "SensorInput1": {
+# // "Type": "temperature",
+# // "Value": 30.0,
+# // "LowThd": 0.0,
+# // "HighThd": 100.0"
+# // },
+# // "SensorInput2": {
+# // "Type": "voltage",
+# // "Value": 0.5,
+# // "LowThd": 0.0,
+# // "HighThd": 1.5
+# // },
+# // "SensorInput3": {
+# // "Type": "power",
+# // "Value": 2.5,
+# // "LowThd": 0.0,
+# // "HighThd": 5.0
+# // }
+# // },
+# // "SensorName2": {
+# // "SensorInput1": {
+# // "Type": "RPM",
+# // "Value": 2000.0,
+# // "LowThd": 1000.0,
+# // "HighThd": 15000.0
+# // },
+# // "SensorInputName2": {
+# // "Type": "amp",
+# // "Value": 0.1,
+# // "LowThd": 0.0,
+# // "HighThd": 0.3
+# // }
+# // }
+# // }
+
+try:
+ import sys
+ import os
+ import subprocess
+ import click
+ import imp
+ import syslog
+ import types
+ import traceback
+ from tabulate import tabulate
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
+
+VERSION = '1.2'
+
+SYSLOG_IDENTIFIER = "platformutil"
+PLATFORM_PSU_MODULE_NAME = "psuutil"
+PLATFORM_PSU_CLASS_NAME = "PsuUtil"
+
+#gongjian add
+PLATFORM_SENSOR_MODULE_NAME = "sensorutil"
+PLATFORM_SENSOR_CLASS_NAME = "SensorUtil"
+
+PLATFORM_FAN_MODULE_NAME = "fanutil"
+PLATFORM_FAN_CLASS_NAME = "FanUtil"
+#end gongjian add
+
+PLATFORM_ROOT_PATH = '/usr/share/sonic/device'
+PLATFORM_ROOT_PATH_DOCKER = '/usr/share/sonic/platform'
+SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen'
+MINIGRAPH_PATH = '/etc/sonic/minigraph.xml'
+HWSKU_KEY = "DEVICE_METADATA['localhost']['hwsku']"
+PLATFORM_KEY = "DEVICE_METADATA['localhost']['platform']"
+
+# Global platform-specific psuutil class instance
+platform_psuutil = None
+
+#gongjian add
+platform_sensorutil = None
+Platform_fanutil = None
+#end gongjian add
+
+# ========================== Syslog wrappers ==========================
+
+
+def log_info(msg, also_print_to_console=False):
+ syslog.openlog(SYSLOG_IDENTIFIER)
+ syslog.syslog(syslog.LOG_INFO, msg)
+ syslog.closelog()
+
+ if also_print_to_console:
+ click.echo(msg)
+
+
+def log_warning(msg, also_print_to_console=False):
+ syslog.openlog(SYSLOG_IDENTIFIER)
+ syslog.syslog(syslog.LOG_WARNING, msg)
+ syslog.closelog()
+
+ if also_print_to_console:
+ click.echo(msg)
+
+
+def log_error(msg, also_print_to_console=False):
+ syslog.openlog(SYSLOG_IDENTIFIER)
+ syslog.syslog(syslog.LOG_ERR, msg)
+ syslog.closelog()
+
+ if also_print_to_console:
+ click.echo(msg)
+
+
+# ==================== Methods for initialization ====================
+
+# Returns platform and HW SKU
+def get_platform_and_hwsku():
+ try:
+ proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-H', '-v', PLATFORM_KEY],
+ stdout=subprocess.PIPE,
+ shell=False,
+ stderr=subprocess.STDOUT)
+ stdout = proc.communicate()[0]
+ proc.wait()
+ platform = stdout.rstrip('\n')
+
+ proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-d', '-v', HWSKU_KEY],
+ stdout=subprocess.PIPE,
+ shell=False,
+ stderr=subprocess.STDOUT)
+ stdout = proc.communicate()[0]
+ proc.wait()
+ hwsku = stdout.rstrip('\n')
+ except OSError, e:
+ raise OSError("Cannot detect platform")
+
+ return (platform, hwsku)
+
+
+# Loads platform specific psuutil module from source
+def load_platform_util():
+ global platform_psuutil
+ #gongjian add
+ global platform_sensorutil
+ global platform_fanutil
+
+ # Get platform and hwsku
+ (platform, hwsku) = get_platform_and_hwsku()
+
+ # Load platform module from source
+ platform_path = ''
+ if len(platform) != 0:
+ platform_path = "/".join([PLATFORM_ROOT_PATH, platform])
+ else:
+ platform_path = PLATFORM_ROOT_PATH_DOCKER
+ hwsku_path = "/".join([platform_path, hwsku])
+
+ try:
+ module_file_psu = "/".join([platform_path, "plugins", PLATFORM_PSU_MODULE_NAME + ".py"])
+ module_psu = imp.load_source(PLATFORM_PSU_MODULE_NAME, module_file_psu)
+ except IOError, e:
+ log_error("Failed to load platform module '%s': %s" % (PLATFORM_PSU_MODULE_NAME, str(e)), True)
+ return -1
+
+ try:
+ platform_psuutil_class = getattr(module_psu, PLATFORM_PSU_CLASS_NAME)
+ platform_psuutil = platform_psuutil_class()
+ except AttributeError, e:
+ log_error("Failed to instantiate '%s' class: %s" % (PLATFORM_PSU_CLASS_NAME, str(e)), True)
+ return -2
+
+
+ #gongjian add
+ try:
+ module_file_sensor = "/".join([platform_path, "plugins", PLATFORM_SENSOR_MODULE_NAME + ".py"])
+ module_sensor = imp.load_source(PLATFORM_SENSOR_MODULE_NAME, module_file_sensor)
+ except IOError, e:
+ log_error("Failed to load platform module '%s': %s" % (PLATFORM_SENSOR_MODULE_NAME, str(e)), True)
+ return -1
+
+ try:
+ platform_sensorutil_class = getattr(module_sensor, PLATFORM_SENSOR_CLASS_NAME)
+ platform_sensorutil = platform_sensorutil_class()
+ except AttributeError, e:
+ log_error("Failed to instantiate '%s' class: %s" % (PLATFORM_SENSOR_CLASS_NAME, str(e)), True)
+ return -2
+
+ try:
+ module_file_fan = "/".join([platform_path, "plugins", PLATFORM_FAN_MODULE_NAME + ".py"])
+ module_fan = imp.load_source(PLATFORM_FAN_MODULE_NAME, module_file_fan)
+ except IOError, e:
+ log_error("Failed to load platform module '%s': %s" % (PLATFORM_FAN_MODULE_NAME, str(e)), True)
+ return -1
+
+ try:
+ platform_fanutil_class = getattr(module_fan, PLATFORM_FAN_CLASS_NAME)
+ platform_fanutil = platform_fanutil_class()
+ except AttributeError, e:
+ log_error("Failed to instantiate '%s' class: %s" % (PLATFORM_FAN_CLASS_NAME, str(e)), True)
+ return -2
+ #end gongjian add
+ return 0
+
+
+# ==================== CLI commands and groups ====================
+
+
+# This is our main entrypoint - the main 'psuutil' command
+@click.group()
+def cli():
+ """platformutil - Command line utility for providing platform status"""
+
+ if os.geteuid() != 0:
+ click.echo("Root privileges are required for this operation")
+ sys.exit(1)
+
+ # Load platform-specific psuutil, fanutil and sensorutil class
+ err = load_platform_util()
+ if err != 0:
+ sys.exit(2)
+
+#'fan' subcommand
+@cli.group()
+@click.pass_context
+def fan(ctx):
+ """fan state"""
+ ctx.obj = "fan"
+
+# 'sensor' subcommand
+@cli.group()
+@click.pass_context
+def sensor(ctx):
+ """sensor state"""
+ ctx.obj = "sensor"
+
+# 'psu' subcommand
+@cli.group()
+@click.pass_context
+def psu(ctx):
+ """psu state"""
+ ctx.obj = "psu"
+
+# 'version' subcommand
+@cli.command()
+def version():
+ """Display version info"""
+ click.echo("platformutil version {0}".format(VERSION))
+
+
+# 'num' subcommand
+@click.command()
+@click.pass_context
+def num(ctx):
+ """Display number of supported sensor/fan/psu device"""
+ if ctx.obj == "psu":
+ click.echo(str(platform_psuutil.get_num_psus()))
+ if ctx.obj == "fan":
+ click.echo(str(len(platform_fanutil.get_fans_name_list())))
+ if ctx.obj == "sensor":
+ click.echo(str(platform_sensorutil.get_num_sensors()))
+
+psu.add_command(num)
+sensor.add_command(num)
+fan.add_command(num)
+
+# 'status' subcommand
+#all API should return "N/A" or float("-intf") if not supported
+@click.command()
+@click.pass_context
+def status(ctx):
+ if ctx.obj == 'psu':
+ psu_dict = platform_psuutil.get_all()
+ if psu_dict == None:
+ print 'Error: psuutil.get_all() failed'
+ return
+
+ psu_nr = psu_dict.get('Number')
+ if psu_nr == None:
+ print 'Error: PSU get all format invalid, prop "Number" missing.'
+ return
+
+ psu_names = [ k for k in psu_dict.keys() if cmp('Number', k) != 0 ]
+ psu_names.sort()
+ header = ['PSU', 'Presence', 'InputStatus', 'InputType', 'OutputStatus', 'PN', 'SN', 'AirFlow']
+ status_table = []
+ for psu_name in psu_names:
+ psu = psu_dict[psu_name]
+ presence = psu.get('Present')
+ pn = psu.get('PN')
+ sn = psu.get('SN')
+ in_status = psu.get('InputStatus')
+ out_status = psu.get('OutputStatus')
+ in_type = psu.get('InputType')
+ airflow = psu.get('AirFlow')
+
+ if presence == None:
+ print 'Error: PSU get all format invaid, prop "Present" is missing.'
+ continue
+ elif presence == False:
+ presence = 'NOT_PRESENT'
+ in_status = 'N/A'
+ out_status = 'N/A'
+ in_type = 'N/A'
+ pn = 'N/A'
+ pn = 'N/A'
+ else:
+ presence = 'PRESENT'
+ if in_status == None:
+ in_status = 'N/A'
+ elif in_status == True:
+ in_status = 'OK'
+ else:
+ in_status = 'NOT_OK'
+
+ if in_type == None:
+ in_type = 'N/A'
+
+ if out_status == None:
+ out_status = 'N/A'
+ elif out_status == True:
+ out_status = 'OK'
+ else:
+ out_status = 'NOT_OK'
+
+ if pn == None:
+ pn = 'N/A'
+ if sn == None:
+ sn = 'N/A'
+ if airflow == None:
+ airflow = 'N/A'
+ status_table.append([psu_name, presence, in_status, in_type, out_status, pn, sn, airflow])
+
+ if len(status_table) != psu_nr:
+ print 'Error: PSU get all missing some PSU information.'
+
+ if len(status_table) > 0:
+ click.echo(tabulate(status_table, header, tablefmt='simple'))
+
+ if ctx.obj == 'fan':
+ fan_dict = platform_fanutil.get_all()
+ if fan_dict == None:
+ print 'Error: fanutil.get_all() failed'
+ return
+
+ fan_nr = fan_dict.get('Number')
+ if fan_nr == None:
+ print 'Error: FAN get all format invalid, prop "Number" missing.'
+ return
+
+ header = [ 'FAN', 'Presence', 'Status', 'Speed', 'LowThd', 'HighThd', 'PN', 'SN', 'AirFlow' ]
+ status_table = []
+ fan_names = [ k for k in fan_dict.keys() if cmp('Number', k) != 0 ]
+ fan_names.sort()
+ for fan_name in fan_names:
+ fan = fan_dict[fan_name]
+ presence = fan.get('Present')
+ speed = fan.get('Speed')
+ low = fan.get('LowThd')
+ high = fan.get('HighThd')
+ pn = fan.get('PN')
+ sn = fan.get('SN')
+ status = fan.get('Status')
+ airflow = fan.get('AirFlow')
+
+ if presence == None:
+ print 'Error: FAN get all format invaid, prop "Present" missing.'
+ continue
+ elif presence == False:
+ presence = 'NOT_PRESENT'
+ status = 'N/A'
+ speed = 'N/A'
+ low = 'N/A'
+ high = 'N/A'
+ pn = 'N/A'
+ sn = 'N/A'
+ airflow = 'N/A'
+ else:
+ presence = 'PRESENT'
+ if status == None:
+ status = 'N/A'
+ elif status == True:
+ status = 'OK'
+ else:
+ status = 'NOT_OK'
+ if airflow == None:
+ airflow = 'N/A'
+ if speed == None:
+ speed = 'N/A'
+ if low == None:
+ low = 'N/A'
+ if high == None:
+ high = 'N/A'
+ if pn == None:
+ pn = 'N/A'
+ if sn == None:
+ sn = 'N/A'
+
+ status_table.append([fan_name, presence, status, speed, low, high, pn, sn, airflow])
+
+ if len(status_table) != fan_nr:
+ print 'Error: FAN get all missing some FAN information.'
+
+ if len(status_table) > 0:
+ click.echo(tabulate(status_table, header, tablefmt='simple'))
+
+ if ctx.obj == 'sensor':
+ sensor_dict = platform_sensorutil.get_all()
+ if sensor_dict == None:
+ print 'Error: sensors.get_all() failed'
+ return
+
+ header = [ 'Sensor', 'InputName', 'State', 'Value', 'LowThd', 'HighThd' ]
+ status_table = []
+ type2unit = { 'temperature' : ' C', 'voltage' : ' V', 'RPM' : ' RPM', 'amp' : ' A', 'power' : ' W'}
+ type_keys = type2unit.keys()
+ for sensor_name, sensor_obj in sensor_dict.items():
+ if cmp(sensor_name, 'Number') == 0:
+ continue
+
+ si_names = [ k for k in sensor_obj.keys() ]
+ si_names.sort()
+ for si_name in si_names:
+ si = sensor_obj[si_name]
+ if si_name == "Sys_AirFlow":
+ status = 'OK'
+ airflow = si
+ status_table.append([sensor_name, si_name, status, airflow, airflow, airflow])
+ continue
+
+ stype = si.get('Type')
+ sval = si.get('Value')
+ slow = si.get('LowThd')
+ shigh = si.get('HighThd')
+ sunit = ' '
+ fault = False
+ if stype != None:
+ sunit = type2unit.get(stype)
+ if sunit == None:
+ sunit = ' '
+ try:
+ sval = float(sval)
+ except:
+ sval = 0.0
+ fault = True
+
+ try:
+ slow = float(slow)
+ except:
+ slow = 0.0
+ fault = True
+
+ try:
+ shigh = float(shigh)
+ except:
+ shigh = 0.0
+ fault = True
+
+ status = 'NOT_OK'
+ if fault == False and sval > slow and sval < shigh:
+ status = 'OK'
+
+ status_table.append([sensor_name, si_name, status, (str(sval)+sunit), (str(slow)+sunit), (str(shigh)+sunit)])
+
+ if len(status_table) > 0:
+ click.echo(tabulate(status_table, header, tablefmt="simple"))
+
+ return
+
+psu.add_command(status)
+sensor.add_command(status)
+fan.add_command(status)
+
+
+if __name__ == '__main__':
+ cli()
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/power_utils/power b/platform/broadcom/sonic-platform-modules-cel/tools/power_utils/power
new file mode 100755
index 000000000000..e3d42d5c0353
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/power_utils/power
@@ -0,0 +1,86 @@
+#!/bin/bash
+#
+# Copyright 2019-present Celestica. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+#
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+
+prog="$0"
+
+if [[ $EUID -ne 0 ]]; then
+ echo "This script must be run as root"
+ exit 1
+fi
+
+usage() {
+ echo "Usage: power "
+ echo
+ echo "Commands:"
+ echo
+ echo " cycle cpu: To power cycle the CPU"
+ echo
+ echo " cycle system : To reboot the whole system"
+ echo
+}
+
+cpu_cycle() {
+ echo "Power cycling CPU..."
+ curl -m 5 -d '{"data":"/usr/local/bin/wedge_power.sh off;/usr/local/bin/wedge_power.sh on"}' http://240.1.1.1:8080/api/sys/raw
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "Failed to power cycle the CPU"
+ fi
+ return 0
+}
+
+system_cycle() {
+ echo "Power cycling system..."
+ curl -m 5 -d '{"data":"/usr/local/bin/wedge_power.sh off;/usr/local/bin/wedge_power.sh on;reboot"}' http://240.1.1.1:8080/api/sys/raw
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "Failed to power cycle the system"
+ fi
+ return 0
+}
+
+if [ $# -lt 1 ]; then
+ usage
+ exit -1
+fi
+
+command="$1"
+component="$2"
+shift
+
+case "$command" in
+cycle)
+ case "$component" in
+ cpu)
+ cpu_cycle
+ ;;
+ system)
+ system_cycle
+ ;;
+ *)
+ usage
+ exit -1
+ ;;
+ esac
+ ;;
+*)
+ usage
+ exit -1
+ ;;
+esac
+
+exit $?
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/read_optic_temp.py b/platform/broadcom/sonic-platform-modules-cel/tools/read_optic_temp.py
new file mode 100644
index 000000000000..97e4641066ba
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/read_optic_temp.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python
+#
+# read_optic_temp.py
+#
+# Command-line utility for read the temperature of optic modules.
+#
+
+try:
+ import sys
+ import os
+ import subprocess
+ import click
+ import imp
+ import multiprocessing.pool
+ import threading
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
+
+
+PLATFORM_ROOT_PATH = '/usr/share/sonic/device'
+SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen'
+HWSKU_KEY = 'DEVICE_METADATA.localhost.hwsku'
+PLATFORM_KEY = 'DEVICE_METADATA.localhost.platform'
+
+PLATFORM_SPECIFIC_SFP_MODULE_NAME = "sfputil"
+PLATFORM_SPECIFIC_SFP_CLASS_NAME = "SfpUtil"
+
+PLATFORM_SPECIFIC_OPTICTEMP_MODULE_NAME = "optictemputil"
+PLATFORM_SPECIFIC_OPTICTEMP_CLASS_NAME = "OpticTempUtil"
+
+# Global platform-specific psuutil class instance
+platform_optictemputil = None
+platform_sfputil = None
+
+
+# ==================== Methods for initialization ====================
+
+# Returns platform and HW SKU
+def get_platform_and_hwsku():
+ try:
+ proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-H', '-v', PLATFORM_KEY],
+ stdout=subprocess.PIPE,
+ shell=False,
+ stderr=subprocess.STDOUT)
+ stdout = proc.communicate()[0]
+ proc.wait()
+ platform = stdout.rstrip('\n')
+
+ proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-d', '-v', HWSKU_KEY],
+ stdout=subprocess.PIPE,
+ shell=False,
+ stderr=subprocess.STDOUT)
+ stdout = proc.communicate()[0]
+ proc.wait()
+ hwsku = stdout.rstrip('\n')
+ except OSError, e:
+ raise OSError("Cannot detect platform")
+
+ return (platform, hwsku)
+
+
+# Returns path to port config file
+def get_path_to_port_config_file():
+ # Get platform and hwsku
+ (platform, hwsku) = get_platform_and_hwsku()
+
+ # Load platform module from source
+ platform_path = "/".join([PLATFORM_ROOT_PATH, platform])
+ hwsku_path = "/".join([platform_path, hwsku])
+
+ # First check for the presence of the new 'port_config.ini' file
+ port_config_file_path = "/".join([hwsku_path, "port_config.ini"])
+ if not os.path.isfile(port_config_file_path):
+ # port_config.ini doesn't exist. Try loading the legacy 'portmap.ini' file
+ port_config_file_path = "/".join([hwsku_path, "portmap.ini"])
+
+ return port_config_file_path
+
+
+def load_platform_util(module_name, class_name):
+
+ # Get platform and hwsku
+ (platform, hwsku) = get_platform_and_hwsku()
+
+ # Load platform module from source
+ platform_path = "/".join([PLATFORM_ROOT_PATH, platform])
+ hwsku_path = "/".join([platform_path, hwsku])
+
+ try:
+ module_file = "/".join([platform_path, "plugins", module_name + ".py"])
+ module = imp.load_source(module_name, module_file)
+ except IOError, e:
+ print("Failed to load platform module '%s': %s" % (module_name, str(e)))
+ sys.exit(1)
+
+ try:
+ platform_util_class = getattr(module, class_name)
+ platform_util = platform_util_class()
+ except AttributeError, e:
+ print("Failed to instantiate '%s' class: %s" % (class_name, str(e)))
+ sys.exit(1)
+
+ return platform_util
+
+
+def get_optic_temp(port_list):
+ temp_list = []
+ for idx, port_num in enumerate(port_list[0]):
+ temp = platform_optictemputil.get_optic_temp(
+ port_num, port_list[1][idx])
+ temp_list.append(round(float(temp), 2))
+ return temp_list
+
+
+# ========================= CLI commands =========================
+
+# This is our main entrypoint - the main 'opticutil' command
+@click.command()
+@click.option('--port_num', '-p', type=int, help='Specific port number')
+def cli(port_num):
+ """optictemputil - Command line utility for providing platform status"""
+
+ # Check root privileges
+ if os.geteuid() != 0:
+ click.echo("Root privileges are required for this operation")
+ sys.exit(1)
+
+ global platform_optictemputil
+ global platform_sfputil
+
+ # Load platform-specific class
+ platform_sfputil = load_platform_util(
+ PLATFORM_SPECIFIC_SFP_MODULE_NAME, PLATFORM_SPECIFIC_SFP_CLASS_NAME)
+ platform_optictemputil = load_platform_util(
+ PLATFORM_SPECIFIC_OPTICTEMP_MODULE_NAME, PLATFORM_SPECIFIC_OPTICTEMP_CLASS_NAME)
+
+ # Load port config
+ port_config_file_path = get_path_to_port_config_file()
+ platform_sfputil.read_porttab_mappings(port_config_file_path)
+ port_list = platform_sfputil.port_to_i2cbus_mapping
+ port_eeprom_list = platform_sfputil.port_to_eeprom_mapping
+ qsfp_port_list = platform_sfputil.qsfp_ports
+
+ port_dict = {}
+ temp_list = [0]
+ i2c_block_size = 32
+ concurrent = 10
+
+ port_data_list = []
+ port_bus_list = []
+ port_type_list = []
+
+ # Read port temperature
+ if port_num:
+ if port_num not in port_list:
+ click.echo("Invalid port")
+ sys.exit(1)
+ port_list = {port_num: port_list.get(port_num)}
+
+ for port_num, bus_num in port_list.items():
+ port_type = "QSFP" if port_num in qsfp_port_list else "SFP"
+ port_bus_list.append(port_eeprom_list[port_num])
+ port_type_list.append(port_type)
+ if len(port_bus_list) >= i2c_block_size:
+ port_tub = (port_bus_list, port_type_list)
+ port_data_list.append(port_tub)
+ port_bus_list = []
+ port_type_list = []
+
+ if port_bus_list != []:
+ port_tub = (port_bus_list, port_type_list)
+ port_data_list.append(port_tub)
+
+ pool = multiprocessing.pool.ThreadPool(processes=concurrent)
+ temp_list = pool.map(get_optic_temp, port_data_list, chunksize=1)
+ pool.close()
+
+ flat_list = [item for sublist in temp_list for item in sublist]
+ click.echo("| PORT_NO\t| PORT_TYPE\t| TEMPERATURE\t|")
+ for port_num, bus_num in port_list.items():
+ port_type = "QSFP" if port_num in qsfp_port_list else "SFP"
+ temp_idx = port_list.keys().index(port_num)
+ temp = flat_list[temp_idx]
+ click.echo('| {}\t\t| {}\t\t| {}\t\t|'.format(
+ port_num, port_type, temp))
+
+
+if __name__ == '__main__':
+ cli()
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/bmc_vlan.service b/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/bmc_vlan.service
new file mode 100644
index 000000000000..9aeeead72394
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/bmc_vlan.service
@@ -0,0 +1,12 @@
+[Unit]
+Description="Service for add vlan for rsyslog"
+After=network.target
+Before=rsyslog-config.service
+Before=ntp.service
+
+[Service]
+Type=forking
+ExecStart=/bin/sh /usr/local/etc/bmc_vlan.sh
+
+[Install]
+WantedBy=rsyslog.service
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/bmc_vlan.sh b/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/bmc_vlan.sh
new file mode 100644
index 000000000000..1d439915efb0
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/bmc_vlan.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+# Add vlan
+ip link add link eth0 name eth0.4088 type vlan id 4088
+ip addr add 240.1.1.2/30 dev eth0.4088
+ip link set eth0.4088 up
+exit 0
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/sync_bmc.py b/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/sync_bmc.py
new file mode 100644
index 000000000000..3065e8a21ebf
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/sync_bmc.py
@@ -0,0 +1,203 @@
+#!/usr/bin/env python
+
+#############################################################################
+# #
+# Platform and model specific service for send data to BMC #
+# #
+# #
+#############################################################################
+
+import subprocess
+import requests
+import os
+import imp
+import multiprocessing.pool
+import threading
+
+
+PLATFORM_ROOT_PATH = '/usr/share/sonic/device'
+SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen'
+HWSKU_KEY = 'DEVICE_METADATA.localhost.hwsku'
+PLATFORM_KEY = 'DEVICE_METADATA.localhost.platform'
+TEMP_URL = 'http://240.1.1.1:8080/api/sys/temp'
+
+PLATFORM_SPECIFIC_SFP_MODULE_NAME = "sfputil"
+PLATFORM_SPECIFIC_SFP_CLASS_NAME = "SfpUtil"
+
+PLATFORM_SPECIFIC_OPTICTEMP_MODULE_NAME = "optictemputil"
+PLATFORM_SPECIFIC_OPTICTEMP_CLASS_NAME = "OpticTempUtil"
+
+PLATFORM_SPECIFIC_CPUTEMP_MODULE_NAME = "cputemputil"
+PLATFORM_SPECIFIC_CPUTEMP_CLASS_NAME = "CpuTempUtil"
+
+platform_sfputil = None
+platform_optictemputil = None
+platform_cputemputil = None
+
+
+# Returns platform and HW SKU
+def get_platform_and_hwsku():
+ try:
+ proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-H', '-v', PLATFORM_KEY],
+ stdout=subprocess.PIPE,
+ shell=False,
+ stderr=subprocess.STDOUT)
+ stdout = proc.communicate()[0]
+ proc.wait()
+ platform = stdout.rstrip('\n')
+
+ proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-d', '-v', HWSKU_KEY],
+ stdout=subprocess.PIPE,
+ shell=False,
+ stderr=subprocess.STDOUT)
+ stdout = proc.communicate()[0]
+ proc.wait()
+ hwsku = stdout.rstrip('\n')
+ except OSError, e:
+ raise OSError("Cannot detect platform")
+
+ return (platform, hwsku)
+
+
+# Returns path to port config file
+def get_path_to_port_config_file():
+ # Get platform and hwsku
+ (platform, hwsku) = get_platform_and_hwsku()
+
+ # Load platform module from source
+ platform_path = "/".join([PLATFORM_ROOT_PATH, platform])
+ hwsku_path = "/".join([platform_path, hwsku])
+
+ # First check for the presence of the new 'port_config.ini' file
+ port_config_file_path = "/".join([hwsku_path, "port_config.ini"])
+ if not os.path.isfile(port_config_file_path):
+ # port_config.ini doesn't exist. Try loading the legacy 'portmap.ini' file
+ port_config_file_path = "/".join([hwsku_path, "portmap.ini"])
+
+ return port_config_file_path
+
+
+def load_platform_util(module_name, class_name):
+
+ # Get platform and hwsku
+ (platform, hwsku) = get_platform_and_hwsku()
+
+ # Load platform module from source
+ platform_path = "/".join([PLATFORM_ROOT_PATH, platform])
+ hwsku_path = "/".join([platform_path, hwsku])
+
+ try:
+ module_file = "/".join([platform_path, "plugins", module_name + ".py"])
+ module = imp.load_source(module_name, module_file)
+ except IOError, e:
+ print("Failed to load platform module '%s': %s" % (
+ module_name, str(e)), True)
+ return -1
+
+ try:
+ platform_util_class = getattr(module, class_name)
+ platform_util = platform_util_class()
+ except AttributeError, e:
+ print("Failed to instantiate '%s' class: %s" %
+ (class_name, str(e)), True)
+ return -2
+
+ return platform_util
+
+
+def get_optic_temp(port_list):
+ temp_list = []
+ for idx, port_eeprom in enumerate(port_list[0]):
+ temp = platform_optictemputil.get_optic_temp(
+ port_eeprom, port_list[1][idx]) if port_list[2][idx] else 0
+ temp_list.append(round(float(temp), 2))
+ return max(temp_list)
+
+
+def get_max_optic_temp():
+ port_config_file_path = get_path_to_port_config_file()
+ platform_sfputil.read_porttab_mappings(port_config_file_path)
+ port_list = platform_sfputil.port_to_i2cbus_mapping
+ port_eeprom_list = platform_sfputil.port_to_eeprom_mapping
+ qsfp_port_list = platform_sfputil.qsfp_ports
+
+ port_data_list = []
+ temp_list = [0]
+ i2c_block_size = 32
+ concurrent = 10
+
+ port_bus_list = []
+ port_type_list = []
+ port_presence_list = []
+
+ for port_num, bus_num in port_list.items():
+ port_type = "QSFP" if port_num in qsfp_port_list else "SFP"
+ port_bus_list.append(port_eeprom_list[port_num])
+ port_type_list.append(port_type)
+ status = platform_sfputil.get_presence(port_num)
+ port_presence_list.append(status)
+ if len(port_bus_list) >= i2c_block_size:
+ port_tub = (port_bus_list, port_type_list, port_presence_list)
+ port_data_list.append(port_tub)
+ port_bus_list = []
+ port_type_list = []
+ port_presence_list = []
+
+ if port_bus_list != []:
+ port_tub = (port_bus_list, port_type_list, port_presence_list)
+ port_data_list.append(port_tub)
+
+ pool = multiprocessing.pool.ThreadPool(processes=concurrent)
+ temp_list = pool.map(get_optic_temp, port_data_list, chunksize=1)
+ pool.close()
+ return max(temp_list)
+
+
+# Send CPU temperature to BMC.
+def send_cpu_temp():
+ max_cpu_tmp = platform_cputemputil.get_max_cpu_tmp()
+ json_input = {
+ "chip": "cpu",
+ "option": "input",
+ "value": str(int(max_cpu_tmp))
+ }
+ print "send ", json_input
+ requests.post(TEMP_URL, json=json_input)
+
+
+# Send maximum optic module temperature to BMC.
+def send_optic_temp():
+ max_optic_temp = get_max_optic_temp()
+ json_input = {
+ "chip": "optical",
+ "option": "input",
+ "value": str(int(max_optic_temp))
+ }
+ print "send ", json_input
+ requests.post(TEMP_URL, json=json_input)
+
+
+def main():
+ global platform_sfputil
+ global platform_cputemputil
+ global platform_optictemputil
+
+ try:
+ platform_sfputil = load_platform_util(
+ PLATFORM_SPECIFIC_SFP_MODULE_NAME, PLATFORM_SPECIFIC_SFP_CLASS_NAME)
+ platform_cputemputil = load_platform_util(
+ PLATFORM_SPECIFIC_CPUTEMP_MODULE_NAME, PLATFORM_SPECIFIC_CPUTEMP_CLASS_NAME)
+ platform_optictemputil = load_platform_util(
+ PLATFORM_SPECIFIC_OPTICTEMP_MODULE_NAME, PLATFORM_SPECIFIC_OPTICTEMP_CLASS_NAME)
+
+ t1 = threading.Thread(target=send_cpu_temp)
+ t2 = threading.Thread(target=send_optic_temp)
+ t1.start()
+ t2.start()
+ except Exception, e:
+ print e
+ pass
+
+
+if __name__ == "__main__":
+ main()
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/sync_bmc.service b/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/sync_bmc.service
new file mode 100644
index 000000000000..334485342510
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/sync_bmc.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Service for send sensor data value to BMC.
+After=multi-user.target
+
+[Service]
+Type=idle
+ExecStart=/usr/bin/python /usr/local/etc/sync_bmc.py
+
+[Install]
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/sync_bmc.timer b/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/sync_bmc.timer
new file mode 100644
index 000000000000..71666cc99887
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/tools/sync_bmc/sync_bmc.timer
@@ -0,0 +1,10 @@
+[Unit]
+Description=Timer send sensor data value to BMC.
+
+[Timer]
+OnUnitActiveSec=5s
+OnBootSec=5s
+AccuracySec=1us
+
+[Install]
+WantedBy=timers.target
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c b/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c
index 7c258cdfeab7..e8cddf4fad11 100644
--- a/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c
+++ b/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c
@@ -631,7 +631,7 @@ static ssize_t show_fan(struct device *dev,
ret = smf_read_reg16(data, PSU_2_FAN_SPEED);
break;
case 12:
- ret = ~smf_read_reg(data, FAN_TRAY_PRESENCE);
+ ret = (~smf_read_reg(data, FAN_TRAY_PRESENCE) & 0xff);
export_hex = 1;
break;
@@ -682,14 +682,26 @@ static ssize_t show_fan_alarm(struct device *dev,
struct smf_data *data = dev_get_drvdata(dev);
int ret, psu_fan_status=0;
- if(index < 2)
- psu_fan_status = smf_read_reg(data, FAN_STATUS_GROUP_B);
+ if (data->kind == z9100smf) {
+ if ((index % 2) == 0)
+ index = index / 2;
+ else
+ index = (index / 2) + 5;
+ }
+
+ if (data->kind == s6100smf)
+ index = index / 2;
+
+ if (index > 7) {
+ psu_fan_status = ~smf_read_reg(data, FAN_STATUS_GROUP_A);
+ index = index % 8;
+ } else
+ psu_fan_status = ~smf_read_reg(data, FAN_STATUS_GROUP_B);
if (psu_fan_status & (1 << (index)))
ret=0;
-
- if (ret < 0)
- return ret;
+ else
+ ret=1;
return sprintf(buf, "%d\n", ret);
}
@@ -726,12 +738,12 @@ static ssize_t show_psu_fan(struct device *dev,
if (index < FAN_601_FAULT){
fan_status = smf_read_reg(data, PSU_1_FAN_STATUS);
- ret = fan_status & (1 << index);
+ ret = (fan_status >> index) & 1;
}
else{
fan_status = smf_read_reg(data, PSU_2_FAN_STATUS);
- ret = fan_status & (1 << (index - 3));
+ ret = (fan_status >> (index - 3)) & 1;
}
if (ret < 0)
@@ -1319,17 +1331,15 @@ static ssize_t show_current(struct device *dev,
else
ret = smf_read_reg16(data, SWITCH_CURRENT_Z9100 + index * 2);
else if (index < CURR602_INPUT)
- curr = smf_read_reg16(data, PSU_1_INPUT_CURRENT + (index % 4) * 2);
+ ret = smf_read_reg16(data, PSU_1_INPUT_CURRENT + (index % 2) * 2);
else
- curr = smf_read_reg16(data, PSU_2_INPUT_CURRENT + (index % 4) * 2);
+ ret = smf_read_reg16(data, PSU_2_INPUT_CURRENT + (index % 4) * 2);
if (ret < 0)
return ret;
- /* TODO: docs say 10mA, value look like A? */
- if(index < 2)
- curr = ret*1000;
+ curr = ret*10;
return sprintf(buf, "%d\n", curr);
}
diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/control b/platform/broadcom/sonic-platform-modules-dell/debian/control
index f32fa7244acc..0b9514687ce8 100644
--- a/platform/broadcom/sonic-platform-modules-dell/debian/control
+++ b/platform/broadcom/sonic-platform-modules-dell/debian/control
@@ -7,30 +7,30 @@ Standards-Version: 3.9.3
Package: platform-modules-s6000
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: platform-modules-z9100
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: platform-modules-s6100
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: platform-modules-z9264f
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: platform-modules-s5232f
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: platform-modules-s5248f
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6000.install b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6000.install
index c2dcb5dc03a9..f662e751a3f8 100644
--- a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6000.install
+++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6000.install
@@ -1,6 +1,8 @@
s6000/scripts/s6000_platform.sh usr/local/bin
s6000/scripts/reset-qsfp usr/local/bin
s6000/scripts/set-fan-speed usr/local/bin
+s6000/scripts/fancontrol.sh usr/local/bin
s6000/systemd/platform-modules-s6000.service etc/systemd/system
+s6000/systemd/fancontrol.service etc/systemd/system
common/io_rd_wr.py usr/local/bin
s6000/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-dell_s6000_s1220-r0
diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6000.postinst b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6000.postinst
index a9b90fa86f3a..052e5a6f574e 100644
--- a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6000.postinst
+++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6000.postinst
@@ -4,4 +4,9 @@
depmod -a
systemctl enable platform-modules-s6000.service
systemctl start platform-modules-s6000.service
+
+systemctl enable fancontrol.service
+systemctl start fancontrol.service
+
+
#DEBHELPER#
diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/modules/dell_s5232f_fpga_ocores.c b/platform/broadcom/sonic-platform-modules-dell/s5232f/modules/dell_s5232f_fpga_ocores.c
index f66f5f18a708..c50d07a05a53 100644
--- a/platform/broadcom/sonic-platform-modules-dell/s5232f/modules/dell_s5232f_fpga_ocores.c
+++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/modules/dell_s5232f_fpga_ocores.c
@@ -1,25 +1,25 @@
/*
- * Copyright (C) 2018 Dell Inc
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
+* Copyright (C) 2018 Dell Inc
+*
+* Licensed under the GNU General Public License Version 2
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+*/
-/**********************************************************************
- * @file fpga_ocores.c
- * @brief This is a driver to interface with Linux Open Cores driver for FPGA i2c access
- *
- ************************************************************************/
+/**
+* @file fpga_i2ccore.c
+* @brief This is a driver to interface with Linux Open Cores drivber for FPGA i2c access
+*
+************************************************************************/
#include
#include
#include
@@ -67,30 +67,29 @@ static const size_t BUF_SIZE = PAGE_SIZE;
/* Device data used by this driver. */
struct fpgapci_dev {
- /* the kernel pci device data structure */
- struct pci_dev *pci_dev;
-
- /* upstream root node */
- struct pci_dev *upstream;
+ /* the kernel pci device data structure */
+ struct pci_dev *pci_dev;
- /* kernels virtual addr. for the mapped BARs */
- void * __iomem bar[PCI_NUM_BARS];
+ /* upstream root node */
+ struct pci_dev *upstream;
- /* length of each memory region. Used for error checking. */
- size_t bar_length[PCI_NUM_BARS];
+ /* kernels virtual addr. for the mapped BARs */
+ void * __iomem bar[PCI_NUM_BARS];
- /* Debug data */
- /* number of hw interrupts handled. */
- int num_handled_interrupts;
- int num_undelivered_signals;
- int pci_gen;
- int pci_num_lanes;
+ /* length of each memory region. Used for error checking. */
+ size_t bar_length[PCI_NUM_BARS];
- unsigned int irq_first;
- unsigned int irq_length;
- unsigned int irq_assigned;
- unsigned int xcvr_intr_count;
+ /* Debug data */
+ /* number of hw interrupts handled. */
+ int num_handled_interrupts;
+ int num_undelivered_signals;
+ int pci_gen;
+ int pci_num_lanes;
+ unsigned int irq_first;
+ unsigned int irq_length;
+ unsigned int irq_assigned;
+ unsigned int xcvr_intr_count;
};
static int use_irq = 1;
@@ -100,7 +99,7 @@ MODULE_PARM_DESC(use_irq, "Get an use_irq value from user...\n");
static uint32_t num_bus = 0;
module_param(num_bus, int, 0);
MODULE_PARM_DESC(num_bus,
- "Number of i2c busses supported by the FPGA on this platform.");
+ "Number of i2c busses supported by the FPGA on this platform.");
/* Xilinx FPGA PCIE info: */
@@ -125,14 +124,14 @@ typedef unsigned long long u64;
/* struct to hold data related to the pcie device */
struct pci_data_struct{
- struct pci_dev* dev;
- unsigned long long phy_addr_bar0;
- unsigned long long phy_len_bar0;
- unsigned long long phy_flags_bar0;
- unsigned int irq_first;
- unsigned int irq_length;
- unsigned int irq_assigned;
- void * kvirt_addr_bar0;
+ struct pci_dev* dev;
+ unsigned long long phy_addr_bar0;
+ unsigned long long phy_len_bar0;
+ unsigned long long phy_flags_bar0;
+ unsigned int irq_first;
+ unsigned int irq_length;
+ unsigned int irq_assigned;
+ void * kvirt_addr_bar0;
};
/* global variable declarations */
@@ -147,55 +146,55 @@ static void free_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev);
struct fpgalogic_i2c {
- void __iomem *base;
- u32 reg_shift;
- u32 reg_io_width;
- wait_queue_head_t wait;
- struct i2c_msg *msg;
- int pos;
- int nmsgs;
- int state; /* see STATE_ */
- int ip_clock_khz;
- int bus_clock_khz;
- void (*reg_set)(struct fpgalogic_i2c *i2c, int reg, u8 value);
- u8 (*reg_get)(struct fpgalogic_i2c *i2c, int reg);
- u32 timeout;
- struct mutex lock;
+ void __iomem *base;
+ u32 reg_shift;
+ u32 reg_io_width;
+ wait_queue_head_t wait;
+ struct i2c_msg *msg;
+ int pos;
+ int nmsgs;
+ int state; /* see STATE_ */
+ int ip_clock_khz;
+ int bus_clock_khz;
+ void (*reg_set)(struct fpgalogic_i2c *i2c, int reg, u8 value);
+ u8 (*reg_get)(struct fpgalogic_i2c *i2c, int reg);
+ u32 timeout;
+ struct mutex lock;
};
/* registers */
-#define FPGAI2C_REG_PRELOW 0
-#define FPGAI2C_REG_PREHIGH 1
-#define FPGAI2C_REG_CONTROL 2
-#define FPGAI2C_REG_DATA 3
-#define FPGAI2C_REG_CMD 4 /* write only */
-#define FPGAI2C_REG_STATUS 4 /* read only, same address as FPGAI2C_REG_CMD */
-#define FPGAI2C_REG_VER 5
+#define FPGAI2C_REG_PRELOW 0
+#define FPGAI2C_REG_PREHIGH 1
+#define FPGAI2C_REG_CONTROL 2
+#define FPGAI2C_REG_DATA 3
+#define FPGAI2C_REG_CMD 4 /* write only */
+#define FPGAI2C_REG_STATUS 4 /* read only, same address as FPGAI2C_REG_CMD */
+#define FPGAI2C_REG_VER 5
-#define FPGAI2C_REG_CTRL_IEN 0x40
-#define FPGAI2C_REG_CTRL_EN 0x80
+#define FPGAI2C_REG_CTRL_IEN 0x40
+#define FPGAI2C_REG_CTRL_EN 0x80
-#define FPGAI2C_REG_CMD_START 0x91
-#define FPGAI2C_REG_CMD_STOP 0x41
-#define FPGAI2C_REG_CMD_READ 0x21
-#define FPGAI2C_REG_CMD_WRITE 0x11
-#define FPGAI2C_REG_CMD_READ_ACK 0x21
-#define FPGAI2C_REG_CMD_READ_NACK 0x29
-#define FPGAI2C_REG_CMD_IACK 0x01
+#define FPGAI2C_REG_CMD_START 0x91
+#define FPGAI2C_REG_CMD_STOP 0x41
+#define FPGAI2C_REG_CMD_READ 0x21
+#define FPGAI2C_REG_CMD_WRITE 0x11
+#define FPGAI2C_REG_CMD_READ_ACK 0x21
+#define FPGAI2C_REG_CMD_READ_NACK 0x29
+#define FPGAI2C_REG_CMD_IACK 0x01
-#define FPGAI2C_REG_STAT_IF 0x01
-#define FPGAI2C_REG_STAT_TIP 0x02
-#define FPGAI2C_REG_STAT_ARBLOST 0x20
-#define FPGAI2C_REG_STAT_BUSY 0x40
-#define FPGAI2C_REG_STAT_NACK 0x80
+#define FPGAI2C_REG_STAT_IF 0x01
+#define FPGAI2C_REG_STAT_TIP 0x02
+#define FPGAI2C_REG_STAT_ARBLOST 0x20
+#define FPGAI2C_REG_STAT_BUSY 0x40
+#define FPGAI2C_REG_STAT_NACK 0x80
/* SR[7:0] - Status register */
-#define FPGAI2C_REG_SR_RXACK (1 << 7) /* Receive acknowledge from slave �1� = No acknowledge received*/
-#define FPGAI2C_REG_SR_BUSY (1 << 6) /* Busy, I2C bus busy (as defined by start / stop bits) */
-#define FPGAI2C_REG_SR_AL (1 << 5) /* Arbitration lost - fpga i2c logic lost arbitration */
-#define FPGAI2C_REG_SR_TIP (1 << 1) /* Transfer in progress */
-#define FPGAI2C_REG_SR_IF (1 << 0) /* Interrupt flag */
+#define FPGAI2C_REG_SR_RXACK (1 << 7) /* Receive acknowledge from slave .1. = No acknowledge received*/
+#define FPGAI2C_REG_SR_BUSY (1 << 6) /* Busy, I2C bus busy (as defined by start / stop bits) */
+#define FPGAI2C_REG_SR_AL (1 << 5) /* Arbitration lost - fpga i2c logic lost arbitration */
+#define FPGAI2C_REG_SR_TIP (1 << 1) /* Transfer in progress */
+#define FPGAI2C_REG_SR_IF (1 << 0) /* Interrupt flag */
enum {
STATE_DONE = 0,
@@ -205,15 +204,16 @@ enum {
STATE_START,
STATE_WRITE,
STATE_READ,
+ STATE_STOP,
STATE_ERROR,
};
-#define TYPE_FPGALOGIC 0
-#define TYPE_GRLIB 1
+#define TYPE_FPGALOGIC 0
+#define TYPE_GRLIB 1
/*I2C_CH1 Offset address from PCIE BAR 0*/
-#define FPGALOGIC_I2C_BASE 0x00006000
-#define FPGALOGIC_CH_OFFSET 0x10
+#define FPGALOGIC_I2C_BASE 0x00006000
+#define FPGALOGIC_CH_OFFSET 0x10
#define i2c_bus_controller_numb 1
#define I2C_PCI_MAX_BUS (16)
@@ -316,58 +316,58 @@ enum {
static int total_i2c_pci_bus = 0;
static uint32_t board_rev_type = 0;
-static struct fpgalogic_i2c fpgalogic_i2c[I2C_PCI_MAX_BUS];
-static struct i2c_adapter i2c_pci_adap[I2C_PCI_MAX_BUS];
-static struct mutex i2c_xfer_lock[I2C_PCI_MAX_BUS];
+static struct fpgalogic_i2c fpgalogic_i2c[I2C_PCI_MAX_BUS];
+static struct i2c_adapter i2c_pci_adap[I2C_PCI_MAX_BUS];
+static struct mutex i2c_xfer_lock[I2C_PCI_MAX_BUS];
static void fpgai2c_reg_set_8(struct fpgalogic_i2c *i2c, int reg, u8 value)
{
- iowrite8(value, i2c->base + (reg << i2c->reg_shift));
+ iowrite8(value, i2c->base + (reg << i2c->reg_shift));
}
static void fpgai2c_reg_set_16(struct fpgalogic_i2c *i2c, int reg, u8 value)
{
- iowrite16(value, i2c->base + (reg << i2c->reg_shift));
+ iowrite16(value, i2c->base + (reg << i2c->reg_shift));
}
static void fpgai2c_reg_set_32(struct fpgalogic_i2c *i2c, int reg, u8 value)
{
- iowrite32(value, i2c->base + (reg << i2c->reg_shift));
+ iowrite32(value, i2c->base + (reg << i2c->reg_shift));
}
static void fpgai2c_reg_set_16be(struct fpgalogic_i2c *i2c, int reg, u8 value)
{
- iowrite16be(value, i2c->base + (reg << i2c->reg_shift));
+ iowrite16be(value, i2c->base + (reg << i2c->reg_shift));
}
static void fpgai2c_reg_set_32be(struct fpgalogic_i2c *i2c, int reg, u8 value)
{
- iowrite32be(value, i2c->base + (reg << i2c->reg_shift));
+ iowrite32be(value, i2c->base + (reg << i2c->reg_shift));
}
static inline u8 fpgai2c_reg_get_8(struct fpgalogic_i2c *i2c, int reg)
{
- return ioread8(i2c->base + (reg << i2c->reg_shift));
+ return ioread8(i2c->base + (reg << i2c->reg_shift));
}
static inline u8 fpgai2c_reg_get_16(struct fpgalogic_i2c *i2c, int reg)
{
- return ioread16(i2c->base + (reg << i2c->reg_shift));
+ return ioread16(i2c->base + (reg << i2c->reg_shift));
}
static inline u8 fpgai2c_reg_get_32(struct fpgalogic_i2c *i2c, int reg)
{
- return ioread32(i2c->base + (reg << i2c->reg_shift));
+ return ioread32(i2c->base + (reg << i2c->reg_shift));
}
static inline u8 fpgai2c_reg_get_16be(struct fpgalogic_i2c *i2c, int reg)
{
- return ioread16be(i2c->base + (reg << i2c->reg_shift));
+ return ioread16be(i2c->base + (reg << i2c->reg_shift));
}
static inline u8 fpgai2c_reg_get_32be(struct fpgalogic_i2c *i2c, int reg)
{
- return ioread32be(i2c->base + (reg << i2c->reg_shift));
+ return ioread32be(i2c->base + (reg << i2c->reg_shift));
}
static inline void fpgai2c_reg_set(struct fpgalogic_i2c *i2c, int reg, u8 value)
@@ -384,29 +384,29 @@ static inline u8 fpgai2c_reg_get(struct fpgalogic_i2c *i2c, int reg)
static void fpgai2c_dump(struct fpgalogic_i2c *i2c)
{
- u8 tmp;
+ u8 tmp;
- PRINT("Logic register dump:\n");
+ PRINT("Logic register dump:\n");
- tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_PRELOW);
- PRINT("FPGAI2C_REG_PRELOW (%d) = 0x%x\n",FPGAI2C_REG_PRELOW,tmp);
+ tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_PRELOW);
+ PRINT("FPGAI2C_REG_PRELOW (%d) = 0x%x\n",FPGAI2C_REG_PRELOW,tmp);
- tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_PREHIGH);
- PRINT("FPGAI2C_REG_PREHIGH(%d) = 0x%x\n",FPGAI2C_REG_PREHIGH,tmp);
+ tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_PREHIGH);
+ PRINT("FPGAI2C_REG_PREHIGH(%d) = 0x%x\n",FPGAI2C_REG_PREHIGH,tmp);
- tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_CONTROL);
- PRINT("FPGAI2C_REG_CONTROL(%d) = 0x%x\n",FPGAI2C_REG_CONTROL,tmp);
+ tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_CONTROL);
+ PRINT("FPGAI2C_REG_CONTROL(%d) = 0x%x\n",FPGAI2C_REG_CONTROL,tmp);
- tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_DATA);
- PRINT("FPGAI2C_REG_DATA (%d) = 0x%x\n",FPGAI2C_REG_DATA,tmp);
+ tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_DATA);
+ PRINT("FPGAI2C_REG_DATA (%d) = 0x%x\n",FPGAI2C_REG_DATA,tmp);
- tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_CMD);
- PRINT("FPGAI2C_REG_CMD (%d) = 0x%x\n",FPGAI2C_REG_CMD,tmp);
+ tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_CMD);
+ PRINT("FPGAI2C_REG_CMD (%d) = 0x%x\n",FPGAI2C_REG_CMD,tmp);
}
static void fpgai2c_stop(struct fpgalogic_i2c *i2c)
{
- fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP);
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP);
}
/*
@@ -414,117 +414,117 @@ static void fpgai2c_stop(struct fpgalogic_i2c *i2c)
*/
static int fpgai2c_poll(struct fpgalogic_i2c *i2c)
{
- u8 stat = fpgai2c_reg_get(i2c, FPGAI2C_REG_STATUS);
- struct i2c_msg *msg = i2c->msg;
- u8 addr;
-
- /* Ready? */
- if (stat & FPGAI2C_REG_STAT_TIP)
- return -EBUSY;
-
- if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) {
- /* Stop has been sent */
- fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_IACK);
- if (i2c->state == STATE_ERROR)
- return -EIO;
- return 0;
- }
-
- /* Error? */
- if (stat & FPGAI2C_REG_STAT_ARBLOST) {
- i2c->state = STATE_ERROR;
- fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP);
- return -EAGAIN;
- }
-
- if (i2c->state == STATE_INIT) {
- if (stat & FPGAI2C_REG_STAT_BUSY)
- return -EBUSY;
-
- i2c->state = STATE_ADDR;
- }
-
- if (i2c->state == STATE_ADDR) {
- /* 10 bit address? */
- if (i2c->msg->flags & I2C_M_TEN) {
- addr = 0xf0 | ((i2c->msg->addr >> 7) & 0x6);
- i2c->state = STATE_ADDR10;
- } else {
- addr = (i2c->msg->addr << 1);
- i2c->state = STATE_START;
- }
+ u8 stat = fpgai2c_reg_get(i2c, FPGAI2C_REG_STATUS);
+ struct i2c_msg *msg = i2c->msg;
+ u8 addr;
+
+ /* Ready? */
+ if (stat & FPGAI2C_REG_STAT_TIP)
+ return -EBUSY;
+
+ if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) {
+ /* Stop has been sent */
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_IACK);
+ if (i2c->state == STATE_ERROR)
+ return -EIO;
+ return 0;
+ }
+
+ /* Error? */
+ if (stat & FPGAI2C_REG_STAT_ARBLOST) {
+ i2c->state = STATE_ERROR;
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP);
+ return -EAGAIN;
+ }
+
+ if (i2c->state == STATE_INIT) {
+ if (stat & FPGAI2C_REG_STAT_BUSY)
+ return -EBUSY;
+
+ i2c->state = STATE_ADDR;
+ }
+
+ if (i2c->state == STATE_ADDR) {
+ /* 10 bit address? */
+ if (i2c->msg->flags & I2C_M_TEN) {
+ addr = 0xf0 | ((i2c->msg->addr >> 7) & 0x6);
+ i2c->state = STATE_ADDR10;
+ } else {
+ addr = (i2c->msg->addr << 1);
+ i2c->state = STATE_START;
+ }
- /* Set read bit if necessary */
- addr |= (i2c->msg->flags & I2C_M_RD) ? 1 : 0;
+ /* Set read bit if necessary */
+ addr |= (i2c->msg->flags & I2C_M_RD) ? 1 : 0;
- fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, addr);
- fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_START);
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, addr);
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_START);
- return 0;
- }
+ return 0;
+ }
- /* Second part of 10 bit addressing */
- if (i2c->state == STATE_ADDR10) {
- fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, i2c->msg->addr & 0xff);
- fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_WRITE);
+ /* Second part of 10 bit addressing */
+ if (i2c->state == STATE_ADDR10) {
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, i2c->msg->addr & 0xff);
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_WRITE);
- i2c->state = STATE_START;
- return 0;
- }
+ i2c->state = STATE_START;
+ return 0;
+ }
- if (i2c->state == STATE_START || i2c->state == STATE_WRITE) {
- i2c->state = (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;
+ if (i2c->state == STATE_START || i2c->state == STATE_WRITE) {
+ i2c->state = (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;
- if (stat & FPGAI2C_REG_STAT_NACK) {
- i2c->state = STATE_ERROR;
- fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP);
- return -ENXIO;
- }
- } else {
- msg->buf[i2c->pos++] = fpgai2c_reg_get(i2c, FPGAI2C_REG_DATA);
- }
-
- if (i2c->pos >= msg->len) {
- i2c->nmsgs--;
- i2c->msg++;
- i2c->pos = 0;
- msg = i2c->msg;
-
- if (i2c->nmsgs) {
- if (!(msg->flags & I2C_M_NOSTART)) {
- i2c->state = STATE_ADDR;
- return 0;
- } else {
- i2c->state = (msg->flags & I2C_M_RD)
- ? STATE_READ : STATE_WRITE;
- }
- } else {
- i2c->state = STATE_DONE;
- fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP);
- return 0;
- }
- }
+ if (stat & FPGAI2C_REG_STAT_NACK) {
+ i2c->state = STATE_ERROR;
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP);
+ return -ENXIO;
+ }
+ } else {
+ msg->buf[i2c->pos++] = fpgai2c_reg_get(i2c, FPGAI2C_REG_DATA);
+ }
+
+ if (i2c->pos >= msg->len) {
+ i2c->nmsgs--;
+ i2c->msg++;
+ i2c->pos = 0;
+ msg = i2c->msg;
+
+ if (i2c->nmsgs) {
+ if (!(msg->flags & I2C_M_NOSTART)) {
+ i2c->state = STATE_ADDR;
+ return 0;
+ } else {
+ i2c->state = (msg->flags & I2C_M_RD)
+ ? STATE_READ : STATE_WRITE;
+ }
+ } else {
+ i2c->state = STATE_DONE;
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP);
+ return 0;
+ }
+ }
- if (i2c->state == STATE_READ) {
- fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, i2c->pos == (msg->len - 1) ?
- FPGAI2C_REG_CMD_READ_NACK : FPGAI2C_REG_CMD_READ_ACK);
- } else {
- fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, msg->buf[i2c->pos++]);
- fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_WRITE);
- }
+ if (i2c->state == STATE_READ) {
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, i2c->pos == (msg->len - 1) ?
+ FPGAI2C_REG_CMD_READ_NACK : FPGAI2C_REG_CMD_READ_ACK);
+ } else {
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, msg->buf[i2c->pos++]);
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_WRITE);
+ }
- return 0;
+ return 0;
}
static ssize_t get_mod_msi(struct device *dev, struct device_attribute *devattr, char *buf)
{
int ind = 0, port_status=0, port_irq_status=0;
- struct fpgapci_dev *fpgapci = (struct fpgapci_dev*) dev_get_drvdata(dev);
+ struct fpgapci_dev *fpgapci = (struct fpgapci_dev*) dev_get_drvdata(dev);
PRINT("%s:xcvr_intr_count:%u\n", __FUNCTION__, fpgapci->xcvr_intr_count);
for(ind=0;ind<64;ind++)
{
- port_status = ioread32(fpga_ctl_addr + PORT_STS_OFFSET + (ind*16));
- port_irq_status = ioread32(fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16));
+ port_status = ioread32(fpga_ctl_addr + PORT_STS_OFFSET + (ind*16));
+ port_irq_status = ioread32(fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16));
PRINT("%s:port:%d, port_status:%#x, port_irq_status:%#x\n", __FUNCTION__, ind, port_status, port_irq_status);
}
return sprintf(buf,"0x%04x\n",fpgapci->xcvr_intr_count);
@@ -532,31 +532,31 @@ static ssize_t get_mod_msi(struct device *dev, struct device_attribute *devattr,
static DEVICE_ATTR(port_msi, S_IRUGO, get_mod_msi, NULL);
static struct attribute *port_attrs[] = {
- &dev_attr_port_msi.attr,
- NULL,
+ &dev_attr_port_msi.attr,
+ NULL,
};
static struct attribute_group port_attr_grp = {
- .attrs = port_attrs,
+ .attrs = port_attrs,
};
static irqreturn_t fpgaport_1_32_isr(int irq, void *dev)
{
struct pci_dev *pdev = dev;
- struct fpgapci_dev *fpgapci = (struct fpgapci_dev*) dev_get_drvdata(&pdev->dev);
+ struct fpgapci_dev *fpgapci = (struct fpgapci_dev*) dev_get_drvdata(&pdev->dev);
int ind = 0, port_status=0, port_irq_status=0;
for(ind=0;ind<32;ind++)
{
- port_irq_status = ioread32(fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16));
+ port_irq_status = ioread32(fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16));
if(port_irq_status&(IRQ_LTCH_STS|PRSNT_LTCH_STS))
{
PRINT("%s:port:%d, port_status:%#x, port_irq_status:%#x\n", __FUNCTION__, ind, port_status, port_irq_status);
- //write on clear
- iowrite32( IRQ_LTCH_STS|PRSNT_LTCH_STS,fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16));
+ //write on clear
+ iowrite32( IRQ_LTCH_STS|PRSNT_LTCH_STS,fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16));
}
}
- fpgapci->xcvr_intr_count++;
+ fpgapci->xcvr_intr_count++;
PRINT("%s: xcvr_intr_count:%u\n", __FUNCTION__, fpgapci->xcvr_intr_count);
sysfs_notify(&pdev->dev.kobj, NULL, "port_msi");
return IRQ_HANDLED;
@@ -565,19 +565,18 @@ static irqreturn_t fpgaport_1_32_isr(int irq, void *dev)
static irqreturn_t fpgaport_33_64_isr(int irq, void *dev)
{
struct pci_dev *pdev = dev;
- struct fpgapci_dev *fpgapci = (struct fpgapci_dev*) dev_get_drvdata(&pdev->dev);
+ struct fpgapci_dev *fpgapci = (struct fpgapci_dev*) dev_get_drvdata(&pdev->dev);
int ind = 0, port_status=0, port_irq_status=0;
for(ind=32;ind<64;ind++)
{
- port_irq_status = ioread32(fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16));
+ port_irq_status = ioread32(fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16));
if(port_irq_status| (IRQ_LTCH_STS|PRSNT_LTCH_STS))
{
PRINT("%s:port:%d, port_status:%#x, port_irq_status:%#x\n", __FUNCTION__, ind, port_status, port_irq_status);
- //write on clear
- iowrite32( IRQ_LTCH_STS|PRSNT_LTCH_STS,fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16));
+ iowrite32( IRQ_LTCH_STS|PRSNT_LTCH_STS,fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16));
}
}
- fpgapci->xcvr_intr_count++;
+ fpgapci->xcvr_intr_count++;
PRINT("%s: xcvr_intr_count:%u\n", __FUNCTION__, fpgapci->xcvr_intr_count);
sysfs_notify(&pdev->dev.kobj, NULL, "port_msi");
return IRQ_HANDLED;
@@ -590,10 +589,14 @@ static void fpgai2c_process(struct fpgalogic_i2c *i2c)
PRINT("fpgai2c_process in. status reg :0x%x\n", stat);
- if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) {
+ if ((i2c->state == STATE_STOP) || (i2c->state == STATE_ERROR)) {
/* stop has been sent */
- PRINT("fpgai2c_process FPGAI2C_REG_CMD_IACK stat = 0x%x Set FPGAI2C_REG_CMD(0%x) FPGAI2C_REG_CMD_IACK = 0x%x\n",stat, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_IACK);
+ PRINT("fpgai2c_process FPGAI2C_REG_CMD_IACK stat = 0x%x Set FPGAI2C_REG_CMD(0%x) FPGAI2C_REG_CMD_IACK = 0x%x\n" \
+ ,stat, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_IACK);
fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_IACK);
+ if(i2c->state == STATE_STOP) {
+ i2c->state = STATE_DONE;
+ }
wake_up(&i2c->wait);
return;
}
@@ -628,7 +631,7 @@ static void fpgai2c_process(struct fpgalogic_i2c *i2c)
i2c->pos = 0;
msg = i2c->msg;
- if (i2c->nmsgs) { /* end? */
+ if (i2c->nmsgs) { /* end? */
/* send start? */
if (!(msg->flags & I2C_M_NOSTART)) {
@@ -647,7 +650,7 @@ static void fpgai2c_process(struct fpgalogic_i2c *i2c)
? STATE_READ : STATE_WRITE;
}
} else {
- i2c->state = STATE_DONE;
+ i2c->state = STATE_STOP;
fpgai2c_stop(i2c);
return;
}
@@ -655,9 +658,9 @@ static void fpgai2c_process(struct fpgalogic_i2c *i2c)
if (i2c->state == STATE_READ) {
PRINT("fpgai2c_poll STATE_READ i2c->pos=%d msg->len-1 = 0x%x set FPGAI2C_REG_CMD = 0x%x\n",i2c->pos, msg->len-1,
- i2c->pos == (msg->len-1) ? FPGAI2C_REG_CMD_READ_NACK : FPGAI2C_REG_CMD_READ_ACK);
+ i2c->pos == (msg->len-1) ? FPGAI2C_REG_CMD_READ_NACK : FPGAI2C_REG_CMD_READ_ACK);
fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, i2c->pos == (msg->len-1) ?
- FPGAI2C_REG_CMD_READ_NACK : FPGAI2C_REG_CMD_READ_ACK);
+ FPGAI2C_REG_CMD_READ_NACK : FPGAI2C_REG_CMD_READ_ACK);
} else {
PRINT("fpgai2c_process set FPGAI2C_REG_DATA(0x%x)\n",FPGAI2C_REG_DATA);
fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, msg->buf[i2c->pos++]);
@@ -667,14 +670,14 @@ static void fpgai2c_process(struct fpgalogic_i2c *i2c)
static irqreturn_t fpgai2c_isr(int irq, void *dev_id)
{
- struct fpgalogic_i2c *i2c = dev_id;
- fpgai2c_process(i2c);
+ struct fpgalogic_i2c *i2c = dev_id;
+ fpgai2c_process(i2c);
- return IRQ_HANDLED;
+ return IRQ_HANDLED;
}
void dell_get_mutex(struct fpgalogic_i2c *i2c)
{
- mutex_lock(&i2c->lock);
+ mutex_lock(&i2c->lock);
}
/**
@@ -682,7 +685,7 @@ void dell_get_mutex(struct fpgalogic_i2c *i2c)
*/
void dell_release_mutex(struct fpgalogic_i2c *i2c)
{
- mutex_unlock(&i2c->lock);
+ mutex_unlock(&i2c->lock);
}
static int fpgai2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
@@ -721,8 +724,9 @@ static int fpgai2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
} else {
+ ret = -ETIMEDOUT;
PRINT("Set FPGAI2C_REG_DATA(0%x) val = 0x%x\n",FPGAI2C_REG_DATA,
- (i2c->msg->addr << 1) | ((i2c->msg->flags & I2C_M_RD) ? 1:0));
+ (i2c->msg->addr << 1) | ((i2c->msg->flags & I2C_M_RD) ? 1:0));
fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA,
(i2c->msg->addr << 1) |
@@ -731,136 +735,135 @@ static int fpgai2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
/* Interrupt mode */
if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
- (i2c->state == STATE_DONE), HZ))
- return (i2c->state == STATE_DONE) ? num : -EIO;
- else
- return -ETIMEDOUT;
+ (i2c->state == STATE_DONE), HZ))
+ ret = (i2c->state == STATE_DONE) ? num : -EIO;
+ return ret;
}
}
static int fpgai2c_init(struct fpgalogic_i2c *i2c)
{
- int prescale;
- int diff;
- u8 ctrl;
-
- if (i2c->reg_io_width == 0)
- i2c->reg_io_width = 1; /* Set to default value */
-
- if (!i2c->reg_set || !i2c->reg_get) {
- bool be = 0; //1:big_endian 0:little_endian
-
- switch (i2c->reg_io_width) {
- case 1:
- i2c->reg_set = fpgai2c_reg_set_8;
- i2c->reg_get = fpgai2c_reg_get_8;
- break;
-
- case 2:
- i2c->reg_set = be ? fpgai2c_reg_set_16be : fpgai2c_reg_set_16;
- i2c->reg_get = be ? fpgai2c_reg_get_16be : fpgai2c_reg_get_16;
- break;
-
- case 4:
- i2c->reg_set = be ? fpgai2c_reg_set_32be : fpgai2c_reg_set_32;
- i2c->reg_get = be ? fpgai2c_reg_get_32be : fpgai2c_reg_get_32;
- break;
-
- default:
- PRINT("Unsupported I/O width (%d)\n",
- i2c->reg_io_width);
- return -EINVAL;
- }
- }
+ int prescale;
+ int diff;
+ u8 ctrl;
+
+ if (i2c->reg_io_width == 0)
+ i2c->reg_io_width = 1; /* Set to default value */
+
+ if (!i2c->reg_set || !i2c->reg_get) {
+ bool be = 0; //1:big_endian 0:little_endian
+
+ switch (i2c->reg_io_width) {
+ case 1:
+ i2c->reg_set = fpgai2c_reg_set_8;
+ i2c->reg_get = fpgai2c_reg_get_8;
+ break;
+
+ case 2:
+ i2c->reg_set = be ? fpgai2c_reg_set_16be : fpgai2c_reg_set_16;
+ i2c->reg_get = be ? fpgai2c_reg_get_16be : fpgai2c_reg_get_16;
+ break;
+
+ case 4:
+ i2c->reg_set = be ? fpgai2c_reg_set_32be : fpgai2c_reg_set_32;
+ i2c->reg_get = be ? fpgai2c_reg_get_32be : fpgai2c_reg_get_32;
+ break;
+
+ default:
+ PRINT("Unsupported I/O width (%d)\n",
+ i2c->reg_io_width);
+ return -EINVAL;
+ }
+ }
- ctrl = fpgai2c_reg_get(i2c, FPGAI2C_REG_CONTROL);
+ ctrl = fpgai2c_reg_get(i2c, FPGAI2C_REG_CONTROL);
- PRINT("%s(), line:%d\n", __func__, __LINE__);
- PRINT("i2c->base = 0x%p\n",i2c->base);
-
- PRINT("ctrl = 0x%x\n",ctrl);
- PRINT("set ctrl = 0x%x\n",ctrl & ~(FPGAI2C_REG_CTRL_EN|FPGAI2C_REG_CTRL_IEN));
-
- /* make sure the device is disabled */
- fpgai2c_reg_set(i2c, FPGAI2C_REG_CONTROL, ctrl & ~(FPGAI2C_REG_CTRL_EN|FPGAI2C_REG_CTRL_IEN));
-
- /*
- * I2C Frequency depends on host clock
- * input clock of 100MHz
- * prescale to 100MHz / ( 5*100kHz) -1 = 199 = 0x4F 100000/(5*100)-1=199=0xc7
- */
- prescale = (i2c->ip_clock_khz / (5 * i2c->bus_clock_khz)) - 1;
- prescale = clamp(prescale, 0, 0xffff);
-
- diff = i2c->ip_clock_khz / (5 * (prescale + 1)) - i2c->bus_clock_khz;
- if (abs(diff) > i2c->bus_clock_khz / 10) {
- PRINT("Unsupported clock settings: core: %d KHz, bus: %d KHz\n",
- i2c->ip_clock_khz, i2c->bus_clock_khz);
- return -EINVAL;
- }
+ PRINT("%s(), line:%d\n", __func__, __LINE__);
+ PRINT("i2c->base = 0x%p\n",i2c->base);
- fpgai2c_reg_set(i2c, FPGAI2C_REG_PRELOW, prescale & 0xff);
- fpgai2c_reg_set(i2c, FPGAI2C_REG_PREHIGH, prescale >> 8);
+ PRINT("ctrl = 0x%x\n",ctrl);
+ PRINT("set ctrl = 0x%x\n",ctrl & ~(FPGAI2C_REG_CTRL_EN|FPGAI2C_REG_CTRL_IEN));
- /* Init the device */
- fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_IACK);
- if (!use_irq)
- fpgai2c_reg_set(i2c, FPGAI2C_REG_CONTROL, ctrl | FPGAI2C_REG_CTRL_EN);
- else
- fpgai2c_reg_set(i2c, FPGAI2C_REG_CONTROL, ctrl | FPGAI2C_REG_CTRL_IEN | FPGAI2C_REG_CTRL_EN);
+ /* make sure the device is disabled */
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_CONTROL, ctrl & ~(FPGAI2C_REG_CTRL_EN|FPGAI2C_REG_CTRL_IEN));
- fpgai2c_dump(i2c);
+ /*
+ * I2C Frequency depends on host clock
+ * input clock of 100MHz
+ * prescale to 100MHz / ( 5*100kHz) -1 = 199 = 0x4F 100000/(5*100)-1=199=0xc7
+ */
+ prescale = (i2c->ip_clock_khz / (5 * i2c->bus_clock_khz)) - 1;
+ prescale = clamp(prescale, 0, 0xffff);
- /* Initialize interrupt handlers if not already done */
- init_waitqueue_head(&i2c->wait);
+ diff = i2c->ip_clock_khz / (5 * (prescale + 1)) - i2c->bus_clock_khz;
+ if (abs(diff) > i2c->bus_clock_khz / 10) {
+ PRINT("Unsupported clock settings: core: %d KHz, bus: %d KHz\n",
+ i2c->ip_clock_khz, i2c->bus_clock_khz);
+ return -EINVAL;
+ }
- return 0;
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_PRELOW, prescale & 0xff);
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_PREHIGH, prescale >> 8);
+
+ /* Init the device */
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_IACK);
+ if (!use_irq)
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_CONTROL, ctrl | FPGAI2C_REG_CTRL_EN);
+ else
+ fpgai2c_reg_set(i2c, FPGAI2C_REG_CONTROL, ctrl | FPGAI2C_REG_CTRL_IEN | FPGAI2C_REG_CTRL_EN);
+
+ fpgai2c_dump(i2c);
+
+ /* Initialize interrupt handlers if not already done */
+ init_waitqueue_head(&i2c->wait);
+
+ return 0;
}
static u32 fpgai2c_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static const struct i2c_algorithm fpgai2c_algorithm = {
- .master_xfer = fpgai2c_xfer,
- .functionality = fpgai2c_func,
+ .master_xfer = fpgai2c_xfer,
+ .functionality = fpgai2c_func,
};
static int i2c_pci_add_bus (struct i2c_adapter *adap)
{
- int ret = 0;
- /* Register new adapter */
- adap->algo = &fpgai2c_algorithm;
- ret = i2c_add_numbered_adapter(adap);
- return ret;
+ int ret = 0;
+ /* Register new adapter */
+ adap->algo = &fpgai2c_algorithm;
+ ret = i2c_add_numbered_adapter(adap);
+ return ret;
}
static int i2c_init_internal_data(void)
{
- int i;
+ int i;
PRINT("%s(), line:%d\n", __func__, __LINE__);
- for( i = 0; i < total_i2c_pci_bus; i++ )
- {
- fpgalogic_i2c[i].reg_shift = 0; /* 8 bit registers */
- fpgalogic_i2c[i].reg_io_width = 1; /* 8 bit read/write */
- fpgalogic_i2c[i].timeout = 500;//1000;//1ms
- fpgalogic_i2c[i].ip_clock_khz = 100000;//100000;/* input clock of 100MHz */
- fpgalogic_i2c[i].bus_clock_khz = 100;
- fpgalogic_i2c[i].base = fpga_base_addr + i*FPGALOGIC_CH_OFFSET;
- mutex_init(&fpgalogic_i2c[i].lock);
- fpgai2c_init(&fpgalogic_i2c[i]);
- }
-
- return 0;
+ for( i = 0; i < total_i2c_pci_bus; i++ )
+ {
+ fpgalogic_i2c[i].reg_shift = 0; /* 8 bit registers */
+ fpgalogic_i2c[i].reg_io_width = 1; /* 8 bit read/write */
+ fpgalogic_i2c[i].timeout = 500;//1000;//1ms
+ fpgalogic_i2c[i].ip_clock_khz = 100000;//100000;/* input clock of 100MHz */
+ fpgalogic_i2c[i].bus_clock_khz = 100;
+ fpgalogic_i2c[i].base = fpga_base_addr + i*FPGALOGIC_CH_OFFSET;
+ mutex_init(&fpgalogic_i2c[i].lock);
+ fpgai2c_init(&fpgalogic_i2c[i]);
+ }
+
+ return 0;
}
static int i2c_pci_init (void)
{
- int i;
+ int i;
if (num_bus == 0) {
board_rev_type = ioread32(fpga_ctl_addr + MB_BRD_REV_TYPE);
@@ -868,8 +871,8 @@ static int i2c_pci_init (void)
if ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_00) {
num_bus = I2C_PCI_MAX_BUS_REV00;
} else if (((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_01) ||
- ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_02) ||
- ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_03)) {
+ ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_02) ||
+ ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_03)) {
switch (board_rev_type & MB_BRD_TYPE_MASK){
case BRD_TYPE_S5212_NON_NEBS:
case BRD_TYPE_S5212_NEBS:
@@ -907,46 +910,46 @@ static int i2c_pci_init (void)
}
}
- printk("board_rev_type 0x%x, num_bus 0x%x\n", board_rev_type, num_bus);
- total_i2c_pci_bus = num_bus;
+ printk("board_rev_type 0x%x, num_bus 0x%x\n", board_rev_type, num_bus);
+ total_i2c_pci_bus = num_bus;
- memset (&i2c_pci_adap, 0, sizeof(i2c_pci_adap));
- memset (&fpgalogic_i2c, 0, sizeof(fpgalogic_i2c));
- for(i=0; i < i2c_bus_controller_numb; i++)
- mutex_init(&i2c_xfer_lock[i]);
+ memset (&i2c_pci_adap, 0, sizeof(i2c_pci_adap));
+ memset (&fpgalogic_i2c, 0, sizeof(fpgalogic_i2c));
+ for(i=0; i < i2c_bus_controller_numb; i++)
+ mutex_init(&i2c_xfer_lock[i]);
- /* Initialize driver's itnernal data structures */
- i2c_init_internal_data();
+ /* Initialize driver's itnernal data structures */
+ i2c_init_internal_data();
- for (i = 0 ; i < total_i2c_pci_bus; i ++) {
+ for (i = 0 ; i < total_i2c_pci_bus; i ++) {
- i2c_pci_adap[i].owner = THIS_MODULE;
- i2c_pci_adap[i].class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ i2c_pci_adap[i].owner = THIS_MODULE;
+ i2c_pci_adap[i].class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
- i2c_pci_adap[i].algo_data = &fpgalogic_i2c[i];
- /* /dev/i2c-600 ~ /dev/i2c-615 for FPGA LOGIC I2C channel controller 1-7 */
- i2c_pci_adap[i].nr = i+600;
- sprintf( i2c_pci_adap[ i ].name, "i2c-pci-%d", i );
- /* Add the bus via the algorithm code */
- if( i2c_pci_add_bus( &i2c_pci_adap[ i ] ) != 0 )
- {
- PRINT("Cannot add bus %d to algorithm layer\n", i );
- return( -ENODEV );
- }
- i2c_set_adapdata(&i2c_pci_adap[i], &fpgalogic_i2c[i]);
+ i2c_pci_adap[i].algo_data = &fpgalogic_i2c[i];
+ /* /dev/i2c-600 ~ /dev/i2c-615 for FPGA LOGIC I2C channel controller 1-7 */
+ i2c_pci_adap[i].nr = i+600;
+ sprintf( i2c_pci_adap[ i ].name, "i2c-pci-%d", i );
+ /* Add the bus via the algorithm code */
+ if( i2c_pci_add_bus( &i2c_pci_adap[ i ] ) != 0 )
+ {
+ PRINT("Cannot add bus %d to algorithm layer\n", i );
+ return( -ENODEV );
+ }
+ i2c_set_adapdata(&i2c_pci_adap[i], &fpgalogic_i2c[i]);
- PRINT( "Registered bus id: %s\n", kobject_name(&i2c_pci_adap[ i ].dev.kobj));
- }
+ PRINT( "Registered bus id: %s\n", kobject_name(&i2c_pci_adap[ i ].dev.kobj));
+ }
- return 0;
+ return 0;
}
static void i2c_pci_deinit(void)
{
- int i;
- for( i = 0; i < total_i2c_pci_bus; i++ ){
- i2c_del_adapter(&i2c_pci_adap[i]);
- }
+ int i;
+ for( i = 0; i < total_i2c_pci_bus; i++ ){
+ i2c_del_adapter(&i2c_pci_adap[i]);
+ }
}
@@ -954,61 +957,61 @@ static void i2c_pci_deinit(void)
* Used for re-training and disabling AER. */
static struct pci_dev* find_upstream_dev (struct pci_dev *dev)
{
- struct pci_bus *bus = 0;
- struct pci_dev *bridge = 0;
- struct pci_dev *cur = 0;
- int found_dev = 0;
-
- bus = dev->bus;
- if (bus == 0) {
- PRINT ( "Device doesn't have an associated bus!\n");
- return 0;
- }
-
- bridge = bus->self;
- if (bridge == 0) {
- PRINT ( "Can't get the bridge for the bus!\n");
- return 0;
- }
-
- PRINT ( "Upstream device %x/%x, bus:slot.func %02x:%02x.%02x\n",
- bridge->vendor, bridge->device,
- bridge->bus->number, PCI_SLOT(bridge->devfn), PCI_FUNC(bridge->devfn));
-
- PRINT ( "List of downstream devices:");
- list_for_each_entry (cur, &bus->devices, bus_list) {
- if (cur != 0) {
- PRINT ( " %x/%x", cur->vendor, cur->device);
- if (cur == dev) {
- found_dev = 1;
- }
- }
- }
- PRINT ( "\n");
- if (found_dev) {
- return bridge;
- } else {
- PRINT ( "Couldn't find upstream device!\n");
- return 0;
- }
+ struct pci_bus *bus = 0;
+ struct pci_dev *bridge = 0;
+ struct pci_dev *cur = 0;
+ int found_dev = 0;
+
+ bus = dev->bus;
+ if (bus == 0) {
+ PRINT ( "Device doesn't have an associated bus!\n");
+ return 0;
+ }
+
+ bridge = bus->self;
+ if (bridge == 0) {
+ PRINT ( "Can't get the bridge for the bus!\n");
+ return 0;
+ }
+
+ PRINT ( "Upstream device %x/%x, bus:slot.func %02x:%02x.%02x\n",
+ bridge->vendor, bridge->device,
+ bridge->bus->number, PCI_SLOT(bridge->devfn), PCI_FUNC(bridge->devfn));
+
+ PRINT ( "List of downstream devices:");
+ list_for_each_entry (cur, &bus->devices, bus_list) {
+ if (cur != 0) {
+ PRINT ( " %x/%x", cur->vendor, cur->device);
+ if (cur == dev) {
+ found_dev = 1;
+ }
+ }
+ }
+ PRINT ( "\n");
+ if (found_dev) {
+ return bridge;
+ } else {
+ PRINT ( "Couldn't find upstream device!\n");
+ return 0;
+ }
}
static int scan_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev)
{
- int i;
-
- for (i = 0; i < PCI_NUM_BARS; i++) {
- unsigned long bar_start = pci_resource_start(dev, i);
- if (bar_start) {
- unsigned long bar_end = pci_resource_end(dev, i);
- unsigned long bar_flags = pci_resource_flags(dev, i);
- PRINT ( "BAR[%d] 0x%08lx-0x%08lx flags 0x%08lx",
- i, bar_start, bar_end, bar_flags);
- }
- }
+ int i;
+
+ for (i = 0; i < PCI_NUM_BARS; i++) {
+ unsigned long bar_start = pci_resource_start(dev, i);
+ if (bar_start) {
+ unsigned long bar_end = pci_resource_end(dev, i);
+ unsigned long bar_flags = pci_resource_flags(dev, i);
+ PRINT ( "BAR[%d] 0x%08lx-0x%08lx flags 0x%08lx",
+ i, bar_start, bar_end, bar_flags);
+ }
+ }
- return 0;
+ return 0;
}
@@ -1019,64 +1022,64 @@ static int scan_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev)
*/
static int map_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev)
{
- int i;
+ int i;
- for (i = 0; i < PCI_NUM_BARS; i++){
- phys_addr_t bar_start = pci_resource_start(dev, i);
- phys_addr_t bar_end = pci_resource_end(dev, i);
- unsigned long bar_length = bar_end - bar_start + 1;
- fpgapci->bar_length[i] = bar_length;
+ for (i = 0; i < PCI_NUM_BARS; i++){
+ phys_addr_t bar_start = pci_resource_start(dev, i);
+ phys_addr_t bar_end = pci_resource_end(dev, i);
+ unsigned long bar_length = bar_end - bar_start + 1;
+ fpgapci->bar_length[i] = bar_length;
- if (!bar_start || !bar_end) {
- fpgapci->bar_length[i] = 0;
- continue;
- }
+ if (!bar_start || !bar_end) {
+ fpgapci->bar_length[i] = 0;
+ continue;
+ }
- if (bar_length < 1) {
- PRINT ( "BAR #%d length is less than 1 byte\n", i);
- continue;
- }
+ if (bar_length < 1) {
+ PRINT ( "BAR #%d length is less than 1 byte\n", i);
+ continue;
+ }
- PRINT ( "bar_start=%llx, bar_end=%llx, bar_length=%lx, flag=%lx\n", bar_start,
- bar_end, bar_length, pci_resource_flags(dev, i));
+ PRINT ( "bar_start=%llx, bar_end=%llx, bar_length=%lx, flag=%lx\n", bar_start,
+ bar_end, bar_length, pci_resource_flags(dev, i));
- /* map the device memory or IO region into kernel virtual
- * address space */
- fpgapci->bar[i] = ioremap_nocache (bar_start + FPGALOGIC_I2C_BASE, I2C_PCI_MAX_BUS * FPGALOGIC_CH_OFFSET);
+ /* map the device memory or IO region into kernel virtual
+ * address space */
+ fpgapci->bar[i] = ioremap_nocache (bar_start + FPGALOGIC_I2C_BASE, I2C_PCI_MAX_BUS * FPGALOGIC_CH_OFFSET);
- if (!fpgapci->bar[i]) {
- PRINT ( "Could not map BAR #%d.\n", i);
- return -1;
- }
+ if (!fpgapci->bar[i]) {
+ PRINT ( "Could not map BAR #%d.\n", i);
+ return -1;
+ }
- PRINT ( "BAR[%d] mapped at 0x%p with length %lu.", i,
- fpgapci->bar[i], bar_length);
+ PRINT ( "BAR[%d] mapped at 0x%p with length %lu.", i,
+ fpgapci->bar[i], bar_length);
- if(i == 0) //FPGA register is in the BAR[0]
- {
+ if(i == 0) //FPGA register is in the BAR[0]
+ {
fpga_phys_addr = bar_start;
fpga_ctl_addr = ioremap_nocache (bar_start, FPGA_CTL_REG_SIZE);
fpga_base_addr = fpgapci->bar[i];
- }
+ }
- PRINT ( "BAR[%d] mapped at 0x%p with length %lu.\n", i,
- fpgapci->bar[i], bar_length);
- }
- return 0;
+ PRINT ( "BAR[%d] mapped at 0x%p with length %lu.\n", i,
+ fpgapci->bar[i], bar_length);
+ }
+ return 0;
}
static void free_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev)
{
- int i;
+ int i;
- for (i = 0; i < PCI_NUM_BARS; i++) {
- if (fpgapci->bar[i]) {
- pci_iounmap(dev, fpgapci->bar[i]);
- fpgapci->bar[i] = NULL;
- }
- }
+ for (i = 0; i < PCI_NUM_BARS; i++) {
+ if (fpgapci->bar[i]) {
+ pci_iounmap(dev, fpgapci->bar[i]);
+ fpgapci->bar[i] = NULL;
+ }
+ }
}
#define FPGA_PCI_NAME "FPGA_PCI"
@@ -1089,206 +1092,206 @@ static void free_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev)
* */
static int register_intr_handler(struct pci_dev *dev, int irq_num_id)
{
- int err = 0;
- struct fpgapci_dev *fpgapci = 0;
+ int err = 0;
+ struct fpgapci_dev *fpgapci = 0;
- fpgapci = (struct fpgapci_dev*) dev_get_drvdata(&dev->dev);
- if (fpgapci == 0) {
- PRINT ( ": fpgapci_dev is 0\n");
- return err;
- }
+ fpgapci = (struct fpgapci_dev*) dev_get_drvdata(&dev->dev);
+ if (fpgapci == 0) {
+ PRINT ( ": fpgapci_dev is 0\n");
+ return err;
+ }
if ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_00) {
- /* Request interrupt line for unique function
- * alternatively function will be called from free_irq as well
+ /* Request interrupt line for unique function
+ * alternatively function will be called from free_irq as well
* with flag IRQF_SHARED */
- switch(irq_num_id) {
- /* Currently we only support test vector 2 for FPGA Logic I2C channel
- * controller 1-7 interrupt*/
- case FPGA_MSI_VECTOR_ID_4:
- err = request_irq(dev->irq + irq_num_id, fpgaport_1_32_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, dev);
- PRINT ( "%d: fpgapci_dev: irq: %d, %d\n", __LINE__, dev->irq, irq_num_id);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_5:
- err = request_irq(dev->irq + irq_num_id, fpgaport_33_64_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, dev);
- PRINT ( "%d: fpgapci_dev: irq: %d, %d\n", __LINE__, dev->irq, irq_num_id);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_8:
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, &fpgalogic_i2c[0]);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_9:
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, &fpgalogic_i2c[1]);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_10:
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, &fpgalogic_i2c[2]);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_11:
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, &fpgalogic_i2c[3]);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_12:
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, &fpgalogic_i2c[4]);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_13:
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, &fpgalogic_i2c[5]);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_14:
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, &fpgalogic_i2c[6]);
- fpgapci->irq_assigned++;
- break;
-
- default:
- PRINT("No more interrupt handler for number (%d)\n",
- dev->irq + irq_num_id);
- break;
- }
+ switch(irq_num_id) {
+ /* Currently we only support test vector 2 for FPGA Logic I2C channel
+ * controller 1-7 interrupt*/
+ case FPGA_MSI_VECTOR_ID_4:
+ err = request_irq(dev->irq + irq_num_id, fpgaport_1_32_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, dev);
+ PRINT ( "%d: fpgapci_dev: irq: %d, %d\n", __LINE__, dev->irq, irq_num_id);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_5:
+ err = request_irq(dev->irq + irq_num_id, fpgaport_33_64_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, dev);
+ PRINT ( "%d: fpgapci_dev: irq: %d, %d\n", __LINE__, dev->irq, irq_num_id);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_8:
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, &fpgalogic_i2c[0]);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_9:
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, &fpgalogic_i2c[1]);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_10:
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, &fpgalogic_i2c[2]);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_11:
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, &fpgalogic_i2c[3]);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_12:
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, &fpgalogic_i2c[4]);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_13:
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, &fpgalogic_i2c[5]);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_14:
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, &fpgalogic_i2c[6]);
+ fpgapci->irq_assigned++;
+ break;
+
+ default:
+ PRINT("No more interrupt handler for number (%d)\n",
+ dev->irq + irq_num_id);
+ break;
+ }
} else if (((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_01) ||
- ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_02) ||
- ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_03)) {
- /* FPGA SPEC 4.3.1.34, First i2c channel mapped to vector 8 */
+ ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_02) ||
+ ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_03)) {
+ /* FPGA SPEC 4.3.1.34, First i2c channel mapped to vector 8 */
switch (irq_num_id) {
- case FPGA_MSI_VECTOR_ID_4:
- err = request_irq(dev->irq + irq_num_id, fpgaport_1_32_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, dev);
- PRINT ( "%d: fpgapci_dev: irq: %d, %d\n", __LINE__, dev->irq, irq_num_id);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_5:
- err = request_irq(dev->irq + irq_num_id, fpgaport_33_64_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, dev);
- PRINT ( "%d: fpgapci_dev: irq: %d, %d\n", __LINE__, dev->irq, irq_num_id);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_8:
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, &fpgalogic_i2c[0]);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_9:
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, &fpgalogic_i2c[1]);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_10:
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, &fpgalogic_i2c[2]);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_11:
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, &fpgalogic_i2c[3]);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_12:
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
- FPGA_PCI_NAME, &fpgalogic_i2c[4]);
- fpgapci->irq_assigned++;
- break;
- case FPGA_MSI_VECTOR_ID_13:
- if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_5) {
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
- IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[5]);
- fpgapci->irq_assigned++;
- }
- break;
- case FPGA_MSI_VECTOR_ID_14:
- if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_5) {
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
- IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[6]);
- fpgapci->irq_assigned++;
- }
- break;
- case FPGA_MSI_VECTOR_ID_15:
- /*it is an external interrupt number. Ignore this case */
- break;
- case FPGA_MSI_VECTOR_ID_16:
- if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_7) {
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
- IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[7]);
- fpgapci->irq_assigned++;
- }
- break;
- case FPGA_MSI_VECTOR_ID_17:
- if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_8) {
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
- IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[8]);
- fpgapci->irq_assigned++;
- }
- break;
- case FPGA_MSI_VECTOR_ID_18:
- if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_8) {
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
- IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[9]);
- fpgapci->irq_assigned++;
- }
- break;
- case FPGA_MSI_VECTOR_ID_19:
- if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_10) {
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
- IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[10]);
- fpgapci->irq_assigned++;
- }
- break;
- case FPGA_MSI_VECTOR_ID_20:
- if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_10) {
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
- IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[11]);
- fpgapci->irq_assigned++;
- }
- break;
- case FPGA_MSI_VECTOR_ID_21:
- if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_12) {
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
- IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[12]);
- fpgapci->irq_assigned++;
- }
- break;
- case FPGA_MSI_VECTOR_ID_22:
- if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_12) {
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
- IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[13]);
- fpgapci->irq_assigned++;
- }
- break;
- case FPGA_MSI_VECTOR_ID_23:
- if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_12) {
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
- IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[14]);
- fpgapci->irq_assigned++;
- }
- break;
- case FPGA_MSI_VECTOR_ID_24:
- if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_12) {
- err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
- IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[15]);
- fpgapci->irq_assigned++;
- }
- break;
-
- default:
- PRINT("No more interrupt handler for number (%d)\n",
- dev->irq + irq_num_id);
- break;
+ case FPGA_MSI_VECTOR_ID_4:
+ err = request_irq(dev->irq + irq_num_id, fpgaport_1_32_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, dev);
+ PRINT ( "%d: fpgapci_dev: irq: %d, %d\n", __LINE__, dev->irq, irq_num_id);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_5:
+ err = request_irq(dev->irq + irq_num_id, fpgaport_33_64_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, dev);
+ PRINT ( "%d: fpgapci_dev: irq: %d, %d\n", __LINE__, dev->irq, irq_num_id);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_8:
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, &fpgalogic_i2c[0]);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_9:
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, &fpgalogic_i2c[1]);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_10:
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, &fpgalogic_i2c[2]);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_11:
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, &fpgalogic_i2c[3]);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_12:
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME,
+ FPGA_PCI_NAME, &fpgalogic_i2c[4]);
+ fpgapci->irq_assigned++;
+ break;
+ case FPGA_MSI_VECTOR_ID_13:
+ if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_5) {
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
+ IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[5]);
+ fpgapci->irq_assigned++;
+ }
+ break;
+ case FPGA_MSI_VECTOR_ID_14:
+ if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_5) {
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
+ IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[6]);
+ fpgapci->irq_assigned++;
+ }
+ break;
+ case FPGA_MSI_VECTOR_ID_15:
+ /*it is an external interrupt number. Ignore this case */
+ break;
+ case FPGA_MSI_VECTOR_ID_16:
+ if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_7) {
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
+ IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[7]);
+ fpgapci->irq_assigned++;
+ }
+ break;
+ case FPGA_MSI_VECTOR_ID_17:
+ if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_8) {
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
+ IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[8]);
+ fpgapci->irq_assigned++;
+ }
+ break;
+ case FPGA_MSI_VECTOR_ID_18:
+ if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_8) {
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
+ IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[9]);
+ fpgapci->irq_assigned++;
+ }
+ break;
+ case FPGA_MSI_VECTOR_ID_19:
+ if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_10) {
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
+ IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[10]);
+ fpgapci->irq_assigned++;
+ }
+ break;
+ case FPGA_MSI_VECTOR_ID_20:
+ if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_10) {
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
+ IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[11]);
+ fpgapci->irq_assigned++;
+ }
+ break;
+ case FPGA_MSI_VECTOR_ID_21:
+ if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_12) {
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
+ IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[12]);
+ fpgapci->irq_assigned++;
+ }
+ break;
+ case FPGA_MSI_VECTOR_ID_22:
+ if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_12) {
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
+ IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[13]);
+ fpgapci->irq_assigned++;
+ }
+ break;
+ case FPGA_MSI_VECTOR_ID_23:
+ if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_12) {
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
+ IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[14]);
+ fpgapci->irq_assigned++;
+ }
+ break;
+ case FPGA_MSI_VECTOR_ID_24:
+ if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_12) {
+ err = request_irq(dev->irq + irq_num_id, fpgai2c_isr,
+ IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[15]);
+ fpgapci->irq_assigned++;
+ }
+ break;
+
+ default:
+ PRINT("No more interrupt handler for number (%d)\n",
+ dev->irq + irq_num_id);
+ break;
}
}
- return err;
+ return err;
}
/* Mask for MSI Multi message enable bits */
#define MSI_MME 0x70
@@ -1348,33 +1351,33 @@ enum fpga_irq_type {
#define CAP_REG 0x34
static void msi_set_enable(struct pci_dev *dev, int enable)
{
- int pos,maxvec;
- u16 control;
- int request_private_bits = 4;
+ int pos,maxvec;
+ u16 control;
+ int request_private_bits = 4;
- pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
- if (pos) {
- pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
- maxvec = 1 << ((control & PCI_MSI_FLAGS_QMASK) >> 1);
- PRINT("control = 0x%x maxvec = 0x%x\n", control, maxvec);
- control &= ~PCI_MSI_FLAGS_ENABLE;
+ if (pos) {
+ pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+ maxvec = 1 << ((control & PCI_MSI_FLAGS_QMASK) >> 1);
+ PRINT("control = 0x%x maxvec = 0x%x\n", control, maxvec);
+ control &= ~PCI_MSI_FLAGS_ENABLE;
- /*
- * The PCI 2.3 spec mandates that there are at most 32
- * interrupts. If this device asks for more, only give it one.
- */
- if (request_private_bits > 5) {
- request_private_bits = 0;
- }
+ /*
+ * The PCI 2.3 spec mandates that there are at most 32
+ * interrupts. If this device asks for more, only give it one.
+ */
+ if (request_private_bits > 5) {
+ request_private_bits = 0;
+ }
- /* Update the number of IRQs the device has available to it */
- control &= ~PCI_MSI_FLAGS_QSIZE;
- control |= (request_private_bits << 4);
+ /* Update the number of IRQs the device has available to it */
+ control &= ~PCI_MSI_FLAGS_QSIZE;
+ control |= (request_private_bits << 4);
- pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
- }
+ pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+ }
}
/**
* @brief Enables pcie-device and claims/remaps neccessary bar resources
@@ -1383,211 +1386,212 @@ static void msi_set_enable(struct pci_dev *dev, int enable)
* */
static int fpgapci_setup_device(struct fpgapci_dev *fpgapci,struct pci_dev *dev)
{
- int err = 0;
+ int err = 0;
- /* wake up the pci device */
- err = pci_enable_device(dev);
- if(err) {
- PRINT("failed to enable pci device %d\n", err);
- goto error_pci_en;
- }
+ /* wake up the pci device */
+ err = pci_enable_device(dev);
+ if(err) {
+ PRINT("failed to enable pci device %d\n", err);
+ goto error_pci_en;
+ }
- /* on platforms with buggy ACPI, pdev->msi_enabled may be set to
- * allow pci_enable_device to work. This indicates INTx was not routed
- * and only MSI should be used
- */
+ /* on platforms with buggy ACPI, pdev->msi_enabled may be set to
+ * allow pci_enable_device to work. This indicates INTx was not routed
+ * and only MSI should be used
+ */
- pci_set_master(dev);
+ pci_set_master(dev);
- /* Setup the BAR memory regions */
- err = pci_request_regions(dev, DRIVER_NAME);
- if (err) {
- PRINT("failed to enable pci device %d\n", err);
- goto error_pci_req;
- }
+ /* Setup the BAR memory regions */
+ err = pci_request_regions(dev, DRIVER_NAME);
+ if (err) {
+ PRINT("failed to enable pci device %d\n", err);
+ goto error_pci_req;
+ }
- scan_bars(fpgapci, dev);
+ scan_bars(fpgapci, dev);
- if (map_bars(fpgapci, dev)) {
- goto fail_map_bars;
- }
+ if (map_bars(fpgapci, dev)) {
+ goto fail_map_bars;
+ }
i2c_pci_init();
- return 0;
- /* ERROR HANDLING */
+ return 0;
+ /* ERROR HANDLING */
fail_map_bars:
- pci_release_regions(dev);
+ pci_release_regions(dev);
error_pci_req:
- pci_disable_device(dev);
+ pci_disable_device(dev);
error_pci_en:
- return -ENODEV;
+ return -ENODEV;
}
static int fpgapci_configure_msi(struct fpgapci_dev *fpgapci,struct pci_dev *dev)
{
- int err = 0, i;
- int request_vec;
+ int err = 0, i;
+ int request_vec;
- msi_set_enable(dev,1);
- PRINT("Check MSI capability after msi_set_enable\n");
+ msi_set_enable(dev,1);
+ PRINT("Check MSI capability after msi_set_enable\n");
- /*Above 4.1.12*/
- request_vec = total_i2c_pci_bus;
- err = pci_alloc_irq_vectors(dev, request_vec, pci_msi_vec_count(dev),
- PCI_IRQ_MSI);//PCI_IRQ_AFFINITY | PCI_IRQ_MSI);
+ /*Above 4.1.12*/
+ request_vec = total_i2c_pci_bus;
+ err = pci_alloc_irq_vectors(dev, request_vec, pci_msi_vec_count(dev),
+ PCI_IRQ_MSI);//PCI_IRQ_AFFINITY | PCI_IRQ_MSI);
- if (err <= 0) {
- PRINT("Cannot set MSI vector (%d)\n", err);
- goto error_no_msi;
- } else {
- PRINT("Got %d MSI vectors starting at %d\n", err, dev->irq);
+ if (err <= 0) {
+ PRINT("Cannot set MSI vector (%d)\n", err);
+ goto error_no_msi;
+ } else {
+ PRINT("Got %d MSI vectors starting at %d\n", err, dev->irq);
if ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_00) {
if (err < MSI_VECTOR_REV_00) {
goto error_disable_msi;
}
} else if (((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_01) ||
- ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_02) ||
- ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_03)) {
+ ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_02) ||
+ ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_03)) {
if (err < MSI_VECTOR_REV_01) {
goto error_disable_msi;
}
}
- }
- fpgapci->irq_first = dev->irq;
- fpgapci->irq_length = err;
- fpgapci->irq_assigned = 0;
+ }
+ fpgapci->irq_first = dev->irq;
+ fpgapci->irq_length = err;
+ fpgapci->irq_assigned = 0;
- for(i = 0; i < fpgapci->irq_length; i++) {
- err = register_intr_handler(dev, i);
- if (err) {
- PRINT("Cannot request Interrupt number %d\n", i);
- goto error_pci_req_irq;
- }
- }
+ for(i = 0; i < fpgapci->irq_length; i++) {
+ err = register_intr_handler(dev, i);
+ if (err) {
+ PRINT("Cannot request Interrupt number %d\n", i);
+ goto error_pci_req_irq;
+ }
+ }
- return 0;
+ return 0;
error_pci_req_irq:
- for(i = 0; i < fpgapci->irq_assigned; i++)
- {
- PRINT("free_irq %d i =%d\n",fpgapci->irq_first + i,i);
+ for(i = 0; i < fpgapci->irq_assigned; i++)
+ {
+ PRINT("free_irq %d i =%d\n",fpgapci->irq_first + i,i);
if (i < 7)
free_irq(fpgapci->irq_first + 8 + i, &fpgalogic_i2c[i]);
else
free_irq(fpgapci->irq_first + 8 + i + 1, &fpgalogic_i2c[i]);
- }
+ }
error_disable_msi:
- pci_disable_msi(fpgapci->pci_dev);
+ pci_disable_msi(fpgapci->pci_dev);
error_no_msi:
- return -ENOSPC;
+ return -ENOSPC;
}
static int fpgapci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
- struct fpgapci_dev *fpgapci = 0;
- int status = 0;
+ struct fpgapci_dev *fpgapci = 0;
+ int status = 0;
#ifdef TEST
- PRINT ( " vendor = 0x%x, device = 0x%x, class = 0x%x, bus:slot.func = %02x:%02x.%02x\n",
- dev->vendor, dev->device, dev->class,
- dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+ PRINT ( " vendor = 0x%x, device = 0x%x, class = 0x%x, bus:slot.func = %02x:%02x.%02x\n",
+ dev->vendor, dev->device, dev->class,
+ dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
#endif
- fpgapci = kzalloc(sizeof(struct fpgapci_dev), GFP_KERNEL);
+ fpgapci = kzalloc(sizeof(struct fpgapci_dev), GFP_KERNEL);
- if (!fpgapci) {
- PRINT( "Couldn't allocate memory!\n");
- goto fail_kzalloc;
- }
+ if (!fpgapci) {
+ PRINT( "Couldn't allocate memory!\n");
+ goto fail_kzalloc;
+ }
- fpgapci->pci_dev = dev;
- dev_set_drvdata(&dev->dev, (void*)fpgapci);
+ fpgapci->pci_dev = dev;
+ dev_set_drvdata(&dev->dev, (void*)fpgapci);
- fpgapci->upstream = find_upstream_dev (dev);
- status = sysfs_create_group(&dev->dev.kobj, &port_attr_grp);
- if (status) {
- printk(KERN_INFO "%s:Cannot create sysfs\n", __FUNCTION__);
- }
+ status = sysfs_create_group(&dev->dev.kobj, &port_attr_grp);
+ if (status) {
+ printk(KERN_INFO "%s:Cannot create sysfs\n", __FUNCTION__);
+ }
- if(fpgapci_setup_device(fpgapci,dev)) {
- goto error_no_device;
- }
+ fpgapci->upstream = find_upstream_dev (dev);
- if (use_irq) {
- if(fpgapci_configure_msi(fpgapci,dev)) {
- goto error_cannot_configure;
- }
- }
+ if(fpgapci_setup_device(fpgapci,dev)) {
+ goto error_no_device;
+ }
+ if (use_irq) {
+ if(fpgapci_configure_msi(fpgapci,dev)) {
+ goto error_cannot_configure;
+ }
+ }
- return 0;
- /* ERROR HANDLING */
+
+ return 0;
+ /* ERROR HANDLING */
error_cannot_configure:
- printk("error_cannot_configure\n");
- free_bars (fpgapci, dev);
- pci_release_regions(dev);
- pci_disable_device(dev);
+ printk("error_cannot_configure\n");
+ free_bars (fpgapci, dev);
+ pci_release_regions(dev);
+ pci_disable_device(dev);
error_no_device:
- i2c_pci_deinit();
- printk("error_no_device\n");
+ i2c_pci_deinit();
+ printk("error_no_device\n");
fail_kzalloc:
- return -1;
+ return -1;
}
static void fpgapci_remove(struct pci_dev *dev)
{
- struct fpgapci_dev *fpgapci = 0;
- int i;
- PRINT (": dev is %p\n", dev);
-
- if (dev == 0) {
- PRINT ( ": dev is 0\n");
- return;
- }
-
- fpgapci = (struct fpgapci_dev*) dev_get_drvdata(&dev->dev);
- if (fpgapci == 0) {
- PRINT ( ": fpgapci_dev is 0\n");
- return;
- }
- i2c_pci_deinit();
- //
- if (use_irq)
- {
- for(i = 0; i < fpgapci->irq_assigned; i++)
- {
- PRINT("free_irq %d i =%d\n",fpgapci->irq_first + i,i);
+ struct fpgapci_dev *fpgapci = 0;
+ int i;
+ PRINT (": dev is %p\n", dev);
+
+ if (dev == 0) {
+ PRINT ( ": dev is 0\n");
+ return;
+ }
+
+ fpgapci = (struct fpgapci_dev*) dev_get_drvdata(&dev->dev);
+ if (fpgapci == 0) {
+ PRINT ( ": fpgapci_dev is 0\n");
+ return;
+ }
+ i2c_pci_deinit();
+ //
+ if (use_irq)
+ {
+ for(i = 0; i < fpgapci->irq_assigned; i++)
+ {
+ PRINT("free_irq %d i =%d\n",fpgapci->irq_first + i,i);
if (i < 7)
- free_irq(fpgapci->irq_first + 8 + i, &fpgalogic_i2c[i]);
+ free_irq(fpgapci->irq_first + 8 + i, &fpgalogic_i2c[i]);
else
free_irq(fpgapci->irq_first + 8 + i + 1, &fpgalogic_i2c[i]);
- }
- }
- pci_disable_msi(fpgapci->pci_dev);
- free_bars (fpgapci, dev);
- pci_disable_device(dev);
- pci_release_regions(dev);
+ }
+ }
+ pci_disable_msi(fpgapci->pci_dev);
+ free_bars (fpgapci, dev);
+ pci_disable_device(dev);
+ pci_release_regions(dev);
- kfree (fpgapci);
+ kfree (fpgapci);
}
static const struct pci_device_id fpgapci_ids[] = {
- {PCI_DEVICE(PCI_VENDOR_ID_XILINX, DEVICE)},
- {0, },
+ {PCI_DEVICE(PCI_VENDOR_ID_XILINX, DEVICE)},
+ {0, },
};
MODULE_DEVICE_TABLE(pci, fpgapci_ids);
static struct pci_driver fpgapci_driver = {
- .name = DRIVER_NAME,
- .id_table = fpgapci_ids,
- .probe = fpgapci_probe,
- .remove = fpgapci_remove,
- /* resume, suspend are optional */
+ .name = DRIVER_NAME,
+ .id_table = fpgapci_ids,
+ .probe = fpgapci_probe,
+ .remove = fpgapci_remove,
+ /* resume, suspend are optional */
};
/* Initialize the driver module (but not any device) and register
@@ -1595,21 +1599,21 @@ static struct pci_driver fpgapci_driver = {
static int __init fpgapci_init(void)
{
- if (pci_register_driver(&fpgapci_driver)) {
- PRINT("pci_unregister_driver\n");
- pci_unregister_driver(&fpgapci_driver);
- return -ENODEV;
- }
+ if (pci_register_driver(&fpgapci_driver)) {
+ PRINT("pci_unregister_driver\n");
+ pci_unregister_driver(&fpgapci_driver);
+ return -ENODEV;
+ }
- return 0;
+ return 0;
}
static void __exit fpgapci_exit(void)
{
- PRINT ("fpgapci_exit");
+ PRINT ("fpgapci_exit");
- /* unregister this driver from the PCI bus driver */
- pci_unregister_driver(&fpgapci_driver);
+ /* unregister this driver from the PCI bus driver */
+ pci_unregister_driver(&fpgapci_driver);
}
@@ -1620,3 +1624,4 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("joyce_yu@dell.com");
MODULE_DESCRIPTION ("Driver for FPGA Logic I2C bus");
MODULE_SUPPORTED_DEVICE ("FPGA Logic I2C bus");
+
diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/platform_sensors.py
index 3091d1c9ed44..039a34e5b69b 100755
--- a/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/platform_sensors.py
+++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/platform_sensors.py
@@ -22,11 +22,15 @@
IPMI_SENSOR_DATA = "ipmitool sdr list"
IPMI_SENSOR_DUMP = "/tmp/sdr"
-FAN_PRESENCE = "FAN{0}_prsnt"
PSU_PRESENCE = "PSU{0}_stat"
# Use this for older firmware
# PSU_PRESENCE="PSU{0}_prsnt"
+IPMI_FAN_PRESENCE = "ipmitool sensor get FAN{0}_prsnt"
+IPMI_PSU1_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x31 | awk '{print substr($0,9,1)}'"
+IPMI_PSU2_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x32 | awk '{print substr($0,9,1)}'"
+IPMI_RAW_STORAGE_READ = "ipmitool raw 0x0a 0x11 {0} 0 0 0xa0"
+IPMI_FRU = "ipmitool fru"
ipmi_sdr_list = ""
# Dump sensor registers
@@ -40,9 +44,18 @@ def ipmi_sensor_dump():
status, ipmi_sdr_list = commands.getstatusoutput(ipmi_cmd)
if status:
- logging.error('Failed to execute:' + ipmi_sdr_list)
+ logging.error('Failed to execute: ' + ipmi_sdr_list)
sys.exit(0)
+# Fetch a Fan Status
+
+def get_fan_status(fan_id):
+ ret_status, ipmi_cmd_ret = commands.getstatusoutput(IPMI_FAN_PRESENCE.format(fan_id))
+ if ret_status:
+ logging.error('Failed to execute : %s'%IPMI_FAN_PRESENCE.format(fan_id))
+ sys.exit(0)
+ return(' ' + ipmi_cmd_ret.splitlines()[5].strip(' ').strip('[]'))
+
# Fetch a BMC register
@@ -62,6 +75,35 @@ def get_pmc_register(reg_name):
logging.basicConfig(level=logging.DEBUG)
return output
+#Fetch FRU Data for given fruid
+def get_psu_airflow(psu_id):
+ fru_id = 'PSU' + str(psu_id) + '_fru'
+ ret_status, ipmi_cmd_ret = commands.getstatusoutput(IPMI_FRU)
+ if ret_status:
+ logging.error('Failed to execute ipmitool: '+ IPMI_FRU)
+ sys.exit(0)
+ found_fru = False
+ for line in ipmi_cmd_ret.splitlines():
+ if line.startswith('FRU Device Description') and fru_id in line.split(':')[1] :
+ found_fru = True
+ if found_fru and line.startswith(' Board Product '):
+ return ' B2F' if 'PS/IO' in line else ' F2B'
+ return ''
+
+# Fetch FRU on given offset
+def fetch_raw_fru(dev_id, offset):
+ ret_status, ipmi_cmd_ret = commands.getstatusoutput(IPMI_RAW_STORAGE_READ.format(dev_id))
+ if ret_status:
+ logging.error('Failed to execute ipmitool :' + IPMI_RAW_STORAGE_READ.format(dev_id))
+ sys.exit(0)
+ return int((ipmi_cmd_ret.splitlines()[offset/16]).split(' ')[(offset%16+1)])
+
+
+
+
+def get_fan_airflow(fan_id):
+ Airflow_Direction = [' F2B', ' B2F']
+ return Airflow_Direction[fetch_raw_fru(fan_id+2, 0x46)]
# Print the information for temperature sensors
@@ -93,7 +135,6 @@ def print_temperature_sensors():
def print_fan_tray(tray):
Fan_Status = [' Normal', ' Abnormal']
- Airflow_Direction = ['B2F', 'F2B']
print ' Fan Tray ' + str(tray) + ':'
@@ -152,16 +193,62 @@ def print_fan_tray(tray):
Fan_Status[fan1_status]
print ' Fan2 State: ',\
Fan_Status[fan2_status]
+ print ' Airflow: ',\
+ get_fan_airflow(tray)
print('\nFan Trays:')
for tray in range(1, S5232F_MAX_FAN_TRAYS + 1):
- fan_presence = FAN_PRESENCE.format(tray)
- if (get_pmc_register(fan_presence)):
+ if (get_fan_status(tray) == ' Present'):
print_fan_tray(tray)
else:
- print '\n Fan Tray ' + str(tray + 1) + ': Not present'
+ print ' Fan Tray {}: NOT PRESENT'.format(str(tray))
+
+ def get_psu_presence(index):
+ """
+ Retrieves the presence status of power supply unit (PSU) defined
+ by index
+ :param index: An integer, index of the PSU of which to query status
+ :return: Boolean, True if PSU is plugged, False if not
+ """
+ ret_status = 1
+
+ if index == 1:
+ ret_status, ipmi_cmd_ret = commands.getstatusoutput(IPMI_PSU1_DATA_DOCKER)
+ elif index == 2:
+ ret_status, ipmi_cmd_ret = commands.getstatusoutput(IPMI_PSU2_DATA_DOCKER)
+
+ if ret_status:
+ logging.error('Failed to execute ipmitool :' + IPMI_PSU1_DATA_DOCKER)
+ sys.exit(0)
+
+ psu_status = ipmi_cmd_ret
+ return (int(psu_status, 16) & 1)
+
+ def get_psu_status(index):
+ """
+ Retrieves the presence status of power supply unit (PSU) defined
+ by index
+ :param index: An integer, index of the PSU of which to query status
+ :return: Boolean, True if PSU is plugged, False if not
+ """
+ status = 0
+ ret_status = 1
+ ipmi_cmd_ret = 'f'
+
+ if index == 1:
+ ret_status, ipmi_cmd_ret = commands.getstatusoutput(IPMI_PSU1_DATA_DOCKER)
+ elif index == 2:
+ ret_status, ipmi_cmd_ret = commands.getstatusoutput(IPMI_PSU2_DATA_DOCKER)
+
+ if ret_status:
+ logging.error('Failed to execute ipmitool : ' + IPMI_PSU2_DATA_DOCKER)
+ sys.exit(0)
+
+ psu_status = ipmi_cmd_ret
+
+ return (not int(psu_status, 16) > 1)
# Print the information for PSU1, PSU2
@@ -175,7 +262,6 @@ def print_psu(psu):
PSU_FAN_AIR_FLOW_BIT = 0
Psu_Fan_Presence = ['Present', 'Absent']
Psu_Fan_Status = ['Normal', 'Abnormal']
- Psu_Fan_Airflow = ['B2F', 'F2B']
# print ' Input: ', Psu_Input_Type[psu_input_type]
# print ' Type: ', Psu_Type[psu_type]
@@ -233,15 +319,19 @@ def print_psu(psu):
get_pmc_register('PSU2_In_amp')
print ' Output Current: ',\
get_pmc_register('PSU2_Out_amp')
+ print ' Airflow: ',\
+ get_psu_airflow(psu)
print('\nPSUs:')
for psu in range(1, S5232F_MAX_PSUS + 1):
- psu_presence = PSU_PRESENCE.format(psu)
- if (get_pmc_register(psu_presence)):
- print_psu(psu)
+ #psu_presence = PSU_PRESENCE.format(psu)
+ if not get_psu_presence(psu):
+ print ' PSU{}: NOT PRESENT'.format(psu)
+ elif not get_psu_status(psu) :
+ print ' PSU{}: NOT OK'.format(psu)
else:
- print '\n PSU ', psu, 'Not present'
+ print_psu(psu)
print '\n Total Power: ',\
get_pmc_register('PSU_Total_watt')
diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/s5232f_platform.sh b/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/s5232f_platform.sh
index 18e5ca2d5159..6f9282a604f2 100755
--- a/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/s5232f_platform.sh
+++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/s5232f_platform.sh
@@ -91,6 +91,48 @@ switch_board_led_default() {
resource="/sys/bus/pci/devices/0000:04:00.0/resource0"
python /usr/bin/pcisysfs.py --set --offset 0x24 --val 0x194 --res $resource > /dev/null 2>&1
}
+
+# Readout firmware version of the system and
+# store in /var/log/firmware_versions
+platform_firmware_versions() {
+ FIRMWARE_VERSION_FILE=/var/log/firmware_versions
+ rm -rf ${FIRMWARE_VERSION_FILE}
+ echo "BIOS: `dmidecode -s system-version `" > $FIRMWARE_VERSION_FILE
+ ## Get FPGA version
+ r=`/usr/bin/pcisysfs.py --get --offset 0x00 --res /sys/bus/pci/devices/0000\:04\:00.0/resource0 | sed '1d; s/.*\(....\)$/\1/; s/\(..\{1\}\)/\1./'`
+ r_min=$(echo $r | sed 's/.*\(..\)$/0x\1/')
+ r_maj=$(echo $r | sed 's/^\(..\).*/0x\1/')
+ echo "FPGA: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE
+
+ ## Get BMC Firmware Revision
+ r=`cat /sys/class/ipmi/ipmi0/device/bmc/firmware_revision`
+ echo "BMC: $r" >> $FIRMWARE_VERSION_FILE
+
+ #System CPLD 0x31 on i2c bus 601 ( physical FPGA I2C-2)
+ r_min=`/usr/sbin/i2cget -y 601 0x31 0x0 | sed ' s/.*\(0x..\)$/\1/'`
+ r_maj=`/usr/sbin/i2cget -y 601 0x31 0x1 | sed ' s/.*\(0x..\)$/\1/'`
+ echo "System CPLD: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE
+
+ #Slave CPLD 1 0x30 on i2c bus 600 ( physical FPGA I2C-1)
+ r_min=`/usr/sbin/i2cget -y 600 0x30 0x0 | sed ' s/.*\(0x..\)$/\1/'`
+ r_maj=`/usr/sbin/i2cget -y 600 0x30 0x1 | sed ' s/.*\(0x..\)$/\1/'`
+ echo "Slave CPLD 1: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE
+
+ #Slave CPLD 2 0x31 on i2c bus 600 ( physical FPGA I2C-1)
+ r_min=`/usr/sbin/i2cget -y 600 0x31 0x0 | sed ' s/.*\(0x..\)$/\1/'`
+ r_maj=`/usr/sbin/i2cget -y 600 0x31 0x1 | sed ' s/.*\(0x..\)$/\1/'`
+ echo "Slave CPLD 2: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE
+
+ #Slave CPLD 3 0x32 on i2c bus 600 ( physical FPGA I2C-1)
+ r_min=`/usr/sbin/i2cget -y 600 0x32 0x0 | sed ' s/.*\(0x..\)$/\1/'`
+ r_maj=`/usr/sbin/i2cget -y 600 0x32 0x1 | sed ' s/.*\(0x..\)$/\1/'`
+ echo "Slave CPLD 3: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE
+
+ #Slave CPLD 3 0x32 on i2c bus 600 ( physical FPGA I2C-1)
+ r_min=`/usr/sbin/i2cget -y 600 0x33 0x0 | sed ' s/.*\(0x..\)$/\1/'`
+ r_maj=`/usr/sbin/i2cget -y 600 0x33 0x1 | sed ' s/.*\(0x..\)$/\1/'`
+ echo "Slave CPLD 4: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE
+}
init_devnum
if [ "$1" == "init" ]; then
@@ -106,10 +148,12 @@ if [ "$1" == "init" ]; then
switch_board_modsel
switch_board_led_default
python /usr/bin/qsfp_irq_enable.py
+ platform_firmware_versions
elif [ "$1" == "deinit" ]; then
sys_eeprom "delete_device"
switch_board_qsfp "delete_device"
+ switch_board_sfp "delete_device"
switch_board_qsfp_mux "delete_device"
modprobe -r i2c-mux-pca954x
diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/fancontrol.sh b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/fancontrol.sh
new file mode 100755
index 000000000000..43315e06c930
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/fancontrol.sh
@@ -0,0 +1,189 @@
+#!/bin/bash
+
+LEVEL=99
+INTERVAL=5
+FAULTY_FANTRAY1=1
+FAULTY_FANTRAY2=1
+FAULTY_FANTRAY3=1
+
+# FAN RPM Speed
+IDLE=7000
+LEVEL1=10000
+LEVEL2=13000
+LEVEL3=16000
+LEVEL4=19000
+LEVEL5=19000
+
+I2C_ADAPTER="/sys/class/i2c-adapter/i2c-2/i2c-11"
+SENSOR1="$I2C_ADAPTER/11-004c/hwmon/hwmon*/temp1_input"
+SENSOR2="$I2C_ADAPTER/11-004d/hwmon/hwmon*/temp1_input"
+SENSOR3="$I2C_ADAPTER/11-004e/hwmon/hwmon*/temp1_input"
+
+# Three fan trays with each contains two separate fans
+# fan1-fan4 fan2-fan5 fan3-fan6
+FANTRAY1_FAN1=$I2C_ADAPTER/11-0029/fan1_target
+FANTRAY1_FAN2=$I2C_ADAPTER/11-0029/fan2_target
+FANTRAY2_FAN1=$I2C_ADAPTER/11-0029/fan3_target
+FANTRAY2_FAN2=$I2C_ADAPTER/11-0029/fan4_target
+FANTRAY3_FAN1=$I2C_ADAPTER/11-002a/fan1_target
+FANTRAY3_FAN2=$I2C_ADAPTER/11-002a/fan2_target
+
+FANTRAY1_FAN1_RPM=$I2C_ADAPTER/11-0029/fan1_input
+FANTRAY1_FAN2_RPM=$I2C_ADAPTER/11-0029/fan2_input
+FANTRAY2_FAN1_RPM=$I2C_ADAPTER/11-0029/fan3_input
+FANTRAY2_FAN2_RPM=$I2C_ADAPTER/11-0029/fan4_input
+FANTRAY3_FAN1_RPM=$I2C_ADAPTER/11-002a/fan1_input
+FANTRAY3_FAN2_RPM=$I2C_ADAPTER/11-002a/fan2_input
+
+function check_module
+{
+ MODULE=$1
+ lsmod | grep "$MODULE" > /dev/null
+ ret=$?
+ if [[ $ret = "1" ]]; then
+ echo "$MODULE is not loaded!"
+ exit 1
+ fi
+}
+
+function check_faulty_fan
+{
+
+ # Assume fans in FanTray spins less than 1000 RPM is faulty.
+ # To Maintain temperature assign max speed 16200 RPM to all other fans.
+ # This RPM speed handle temperature upto 75C degrees
+
+ fan1=$(cat $FANTRAY1_FAN1_RPM)
+ fan2=$(cat $FANTRAY1_FAN2_RPM)
+ fan3=$(cat $FANTRAY2_FAN1_RPM)
+ fan4=$(cat $FANTRAY2_FAN2_RPM)
+ fan5=$(cat $FANTRAY3_FAN1_RPM)
+ fan6=$(cat $FANTRAY3_FAN2_RPM)
+
+ # FanTray1
+ if [ "$fan1" -le "1000" ] || [ "$fan2" -le "1000" ]; then
+
+ # First time detecting failure
+ if [ $FAULTY_FANTRAY1 -lt "2" ]; then
+ FAULTY_FANTRAY1=2
+ /usr/local/bin/set-fan-speed 16200 2 > /dev/null
+ logger "Faulty Fans in Fantray1 $fan1 $fan2 Please check."
+ fi
+
+ elif [ "$fan1" -ge "1000" ] || [ "$fan2" -ge "1000" ]; then
+ FAULTY_FANTRAY1=0
+ fi
+
+
+ # FanTray2
+ if [ "$fan3" -le "1000" ] || [ "$fan4" -le "1000" ]; then
+
+ # First time detecting failure
+ if [ $FAULTY_FANTRAY2 -lt "2" ]; then
+
+ FAULTY_FANTRAY2=2
+ /usr/local/bin/set-fan-speed 16200 2 > /dev/null
+ logger "Faulty Fans in FanTray2: $fan3 $fan4. Please check."
+ fi
+
+ elif [ "$fan3" -ge "1000" ] || [ "$fan4" -ge "1000" ]; then
+ FAULTY_FANTRAY2=0
+ fi
+
+ # FanTray3
+ if [ "$fan5" -le "1000" ] || [ "$fan6" -le "1000" ]; then
+
+ # First time detecting failure
+ if [ $FAULTY_FANTRAY3 -lt "2" ]; then
+
+ FAULTY_FANTRAY3=2
+ /usr/local/bin/set-fan-speed 16200 2 > /dev/null
+ logger "FanTray3 Fans are Faulty.. $fan5 $fan6. Please check."
+ fi
+
+ elif [ "$fan5" -ge "1000" ] || [ "$fan6" -ge "1000" ]; then
+
+ FAULTY_FANTRAY3=0
+ fi
+
+}
+
+function update_fan_speed
+{
+ local fan_speed=$1
+
+ echo $fan_speed > $FANTRAY1_FAN1
+ echo $fan_speed > $FANTRAY1_FAN2
+ echo $fan_speed > $FANTRAY2_FAN1
+ echo $fan_speed > $FANTRAY2_FAN2
+ echo $fan_speed > $FANTRAY3_FAN1
+ echo $fan_speed > $FANTRAY3_FAN2
+
+}
+
+function monitor_temp_sensors
+{
+
+ while true # go through all temp sensor outputs
+ do
+ sensor1=$(expr `echo $(cat $SENSOR1)` / 1000)
+ sensor2=$(expr `echo $(cat $SENSOR2)` / 1000)
+ sensor3=$(expr `echo $(cat $SENSOR3)` / 1000)
+ sum=$(($sensor1 + $sensor2 + $sensor3))
+ sensor_temp=$(($sum/3))
+
+ if [ "$sensor_temp" -le "25" ] && [ "$LEVEL" -ne "0" ]
+ then
+ # Set Fan Speed to 7000 RPM"
+ LEVEL=0
+ update_fan_speed $IDLE
+ logger "Adjusted FAN Speed to $IDLE RPM against $sensor_temp Temperature"
+
+ elif [ "$sensor_temp" -ge "26" ] && [ "$sensor_temp" -le "44" ] && [ "$LEVEL" -ne "1" ]
+ then
+ # Set Fan Speed to 10000 RPM"
+ LEVEL=1
+ update_fan_speed $LEVEL1
+ logger "Adjusted FAN Speed to $IDLE RPM against $sensor_temp Temperature"
+
+ elif [ "$sensor_temp" -ge "45" ] && [ "$sensor_temp" -le "59" ] && [ "$LEVEL" -ne "2" ]
+ then
+ # Set Fan Speed to 13000 RPM"
+ LEVEL=2
+ update_fan_speed $LEVEL2
+ logger "Adjusted FAN Speed to $IDLE RPM against $sensor_temp Temperature"
+
+ elif [ "$sensor_temp" -ge "60" ] && [ "$sensor_temp" -le "79" ] && [ "$LEVEL" -ne "3" ]
+ then
+ # Set Fan Speed to 16000 RPM"
+ LEVEL=3
+ update_fan_speed $LEVEL3
+ logger "Adjusted FAN Speed to $IDLE RPM against $sensor_temp Temperature"
+
+ elif [ "$sensor_temp" -ge "80" ] && [ "$LEVEL" -ne "4" ]
+ then
+ # Set Fan Speed to 19000 RPM"
+ LEVEL=4
+ update_fan_speed $LEVEL4
+ logger "Adjusted FAN Speed to $IDLE RPM against $sensor_temp Temperature"
+ fi
+
+ # Check for faulty fan
+ check_faulty_fan
+
+ done
+
+}
+
+# Check drivers for sysfs attributes
+check_module "dell_s6000_platform"
+check_module "max6620"
+
+# main loop calling the main function at specified intervals
+while true
+do
+ monitor_temp_sensors
+ # Sleep while still handling signals
+ sleep $INTERVAL &
+ wait
+done
diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py
index 005fdd15b269..e94a7d1210f5 100755
--- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py
+++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py
@@ -43,6 +43,7 @@ class Chassis(ChassisBase):
reset_reason_dict[0x6] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE
def __init__(self):
+ ChassisBase.__init__(self)
# Initialize SFP list
self.PORT_START = 0
self.PORT_END = 31
@@ -65,7 +66,7 @@ def __init__(self):
# Get Transceiver status
self.modprs_register = self._get_transceiver_status()
- self.sys_eeprom = Eeprom()
+ self._eeprom = Eeprom()
for i in range(MAX_S6000_FAN):
fan = Fan(i)
self._fan_list.append(fan)
@@ -105,7 +106,7 @@ def get_name(self):
Returns:
string: The name of the chassis
"""
- return self.sys_eeprom.modelstr()
+ return self._eeprom.modelstr()
def get_presence(self):
"""
@@ -121,7 +122,7 @@ def get_model(self):
Returns:
string: Model/part number of chassis
"""
- return self.sys_eeprom.part_number_str()
+ return self._eeprom.part_number_str()
def get_serial(self):
"""
@@ -129,7 +130,7 @@ def get_serial(self):
Returns:
string: Serial number of chassis
"""
- return self.sys_eeprom.serial_str()
+ return self._eeprom.serial_str()
def get_status(self):
"""
@@ -148,7 +149,7 @@ def get_base_mac(self):
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
- return self.sys_eeprom.base_mac_addr()
+ return self._eeprom.base_mac_addr()
def get_serial_number(self):
"""
@@ -158,7 +159,7 @@ def get_serial_number(self):
A string containing the hardware serial number for this
chassis.
"""
- return self.sys_eeprom.serial_number_str()
+ return self._eeprom.serial_number_str()
def get_system_eeprom_info(self):
"""
@@ -170,7 +171,7 @@ def get_system_eeprom_info(self):
OCP ONIE TlvInfo EEPROM format and values are their
corresponding values.
"""
- return self.sys_eeprom.system_eeprom_info()
+ return self._eeprom.system_eeprom_info()
def get_reboot_cause(self):
"""
diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py
index 3d824ba28268..a82fd6a70201 100644
--- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py
+++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py
@@ -28,14 +28,15 @@
psu_eeprom_format = [
('PPID', 's', 20), ('DPN Rev', 's', 3), ('Service Tag', 's', 7),
('Part Number', 's', 10), ('Part Num Revision', 's', 3),
- ('Mfg Test', 's', 2), ('PSU Type', 's', 1), ('Fab Rev', 's', 2)
+ ('Mfg Test', 's', 2), ('Redundant copy', 's', 83), ('PSU Type', 's', 1),
+ ('Fab Rev', 's', 2)
]
# Fan eeprom fields in format required by EepromDecoder
fan_eeprom_format = [
('PPID', 's', 20), ('DPN Rev', 's', 3), ('Service Tag', 's', 7),
('Part Number', 's', 10), ('Part Num Revision', 's', 3),
- ('Mfg Test', 's', 2), ('Redundant copy', 's', 82),
+ ('Mfg Test', 's', 2), ('Redundant copy', 's', 83),
('Number of Fans', 's', 1), ('Fan Type', 's', 1),
('Fab Rev', 's', 2)
]
@@ -149,6 +150,10 @@ def _load_device_eeprom(self):
except:
self.serial_number = 'NA'
self.part_number = 'NA'
+ if self.is_psu_eeprom:
+ self.psu_type = 'NA'
+ else:
+ self.fan_type = 'NA'
else:
(valid, data) = self._get_eeprom_field("PPID")
if valid:
@@ -168,11 +173,18 @@ def _load_device_eeprom(self):
else:
self.part_number = 'NA'
- (valid, data) = self._get_eeprom_field("Fan Type")
- if valid:
- self.fan_type = data
+ if self.is_psu_eeprom:
+ (valid, data) = self._get_eeprom_field("PSU Type")
+ if valid:
+ self.psu_type = data
+ else:
+ self.psu_type = 'NA'
else:
- self.fan_type = 'NA'
+ (valid, data) = self._get_eeprom_field("Fan Type")
+ if valid:
+ self.fan_type = data
+ else:
+ self.fan_type = 'NA'
def _get_eeprom_field(self, field_name):
"""
@@ -204,7 +216,10 @@ def airflow_fan_type(self):
"""
Returns the airflow fan type.
"""
- return int(self.fan_type.encode('hex'), 16)
+ if self.is_psu_eeprom:
+ return int(self.psu_type.encode('hex'), 16)
+ else:
+ return int(self.fan_type.encode('hex'), 16)
# System EEPROM specific methods
def base_mac_addr(self):
diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan.py
index 3350b4818401..92f83c8fbc79 100644
--- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan.py
+++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan.py
@@ -11,12 +11,14 @@
try:
import os
+ import glob
from sonic_platform_base.fan_base import FanBase
from sonic_platform.eeprom import Eeprom
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
+MAX_S6000_PSU_FAN_SPEED = 18000
MAX_S6000_FAN_SPEED = 19000
@@ -26,12 +28,13 @@ class Fan(FanBase):
CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0/"
I2C_DIR = "/sys/class/i2c-adapter/"
- def __init__(self, fan_index, psu_fan=False):
- # Fan is 1-based in DellEMC platforms
- self.index = fan_index + 1
+ def __init__(self, fan_index, psu_fan=False, dependency=None):
self.is_psu_fan = psu_fan
+ self.is_driver_initialized = True
if not self.is_psu_fan:
+ # Fan is 1-based in DellEMC platforms
+ self.index = fan_index + 1
self.fan_presence_reg = "fan_prs"
self.fan_led_reg = "fan{}_led".format(fan_index)
self.get_fan_speed_reg = self.I2C_DIR + "i2c-11/11-0029/" +\
@@ -42,8 +45,21 @@ def __init__(self, fan_index, psu_fan=False):
self.max_fan_speed = MAX_S6000_FAN_SPEED
self.supported_led_color = ['off', 'green', 'amber']
else:
- self.get_fan_speed_reg = self.I2C_DIR + "i2c-1/1-005{}/" +\
- "fan1_input".format(10 - self.index)
+ self.index = fan_index
+ self.dependency = dependency
+ self.set_fan_speed_reg = self.I2C_DIR +\
+ "i2c-1/1-005{}/fan1_target".format(10 - self.index)
+
+ hwmon_dir = self.I2C_DIR +\
+ "i2c-1/1-005{}/hwmon/".format(10 - self.index)
+ try:
+ hwmon_node = os.listdir(hwmon_dir)[0]
+ except OSError:
+ hwmon_node = "hwmon*"
+ self.is_driver_initialized = False
+
+ self.get_fan_speed_reg = hwmon_dir + hwmon_node + '/fan1_input'
+ self.max_fan_speed = MAX_S6000_PSU_FAN_SPEED
def _get_cpld_register(self, reg_name):
# On successful read, returns the value read from given
@@ -87,6 +103,14 @@ def _get_i2c_register(self, reg_file):
# reg_name and on failure returns 'ERR'
rv = 'ERR'
+ if not self.is_driver_initialized:
+ reg_file_path = glob.glob(reg_file)
+ if len(reg_file_path):
+ reg_file = reg_file_path[0]
+ self._get_sysfs_path()
+ else:
+ return rv
+
if (not os.path.isfile(reg_file)):
return rv
@@ -116,6 +140,13 @@ def _set_i2c_register(self, reg_file, value):
return rv
+ def _get_sysfs_path(self):
+ fan_speed_reg = glob.glob(self.get_fan_speed_reg)
+
+ if len(fan_speed_reg):
+ self.get_fan_speed_reg = fan_speed_reg[0]
+ self.is_driver_initialized = True
+
def get_name(self):
"""
Retrieves the name of the Fan
@@ -136,6 +167,9 @@ def get_presence(self):
bool: True if Fan is present, False if not
"""
status = False
+ if self.is_psu_fan:
+ return self.dependency.get_presence()
+
fan_presence = self._get_cpld_register(self.fan_presence_reg)
if (fan_presence != 'ERR'):
fan_presence = int(fan_presence,16) & self.index
@@ -151,7 +185,10 @@ def get_model(self):
Returns:
string: Part number of Fan
"""
- return self.eeprom.part_number_str()
+ if not self.is_psu_fan:
+ return self.eeprom.part_number_str()
+ else:
+ return 'NA'
def get_serial(self):
"""
@@ -161,7 +198,10 @@ def get_serial(self):
string: Serial number of Fan
"""
# Sample Serial number format "US-01234D-54321-25A-0123-A00"
- return self.eeprom.serial_number_str()
+ if not self.is_psu_fan:
+ return self.eeprom.serial_number_str()
+ else:
+ return 'NA'
def get_status(self):
"""
@@ -185,11 +225,21 @@ def get_direction(self):
Returns:
A string, either FAN_DIRECTION_INTAKE or
FAN_DIRECTION_EXHAUST depending on fan direction
+
+ Notes:
+ In DellEMC platforms,
+ - Forward/Exhaust : Air flows from Port side to Fan side.
+ - Reverse/Intake : Air flows from Fan side to Port side.
"""
- direction = {1: 'FAN_DIRECTION_INTAKE', 2: 'FAN_DIRECTION_EXHAUST'}
- fan_direction = self.eeprom.airflow_fan_type()
+ if self.is_psu_fan:
+ direction = {1: self.FAN_DIRECTION_EXHAUST, 2: self.FAN_DIRECTION_INTAKE,
+ 3: self.FAN_DIRECTION_EXHAUST, 4: self.FAN_DIRECTION_INTAKE}
+ fan_direction = self.dependency.eeprom.airflow_fan_type()
+ else:
+ direction = {1: self.FAN_DIRECTION_EXHAUST, 2: self.FAN_DIRECTION_INTAKE}
+ fan_direction = self.eeprom.airflow_fan_type()
- return direction.get(fan_direction,'NA')
+ return direction.get(fan_direction, self.FAN_DIRECTION_NOT_APPLICABLE)
def get_speed(self):
"""
@@ -248,7 +298,7 @@ def set_status_led(self, color):
Returns:
bool: True if set success, False if fail.
"""
- if color not in self.supported_led_color:
+ if self.is_psu_fan or (color not in self.supported_led_color):
return False
if(color == self.STATUS_LED_COLOR_AMBER):
color = 'yellow'
@@ -266,6 +316,10 @@ def get_status_led(self):
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings.
"""
+ if self.is_psu_fan:
+ # No LED available for PSU Fan
+ return None
+
fan_led = self._get_cpld_register(self.fan_led_reg)
if (fan_led != 'ERR'):
if (fan_led == 'yellow'):
diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/psu.py
index dfbd2a87eb5d..24200f1c7d39 100644
--- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/psu.py
+++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/psu.py
@@ -11,8 +11,10 @@
try:
import os
+ import glob
from sonic_platform_base.psu_base import PsuBase
from sonic_platform.eeprom import Eeprom
+ from sonic_platform.fan import Fan
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
@@ -28,12 +30,20 @@ def __init__(self, psu_index):
self.index = psu_index + 1
self.psu_presence_reg = "psu{}_prs".format(psu_index)
self.psu_status_reg = "powersupply_status"
+ self.is_driver_initialized = False
if self.index == 1:
ltc_dir = self.I2C_DIR + "i2c-11/11-0042/hwmon/"
else:
ltc_dir = self.I2C_DIR + "i2c-11/11-0040/hwmon/"
- hwmon_node = os.listdir(ltc_dir)[0]
+
+ try:
+ hwmon_node = os.listdir(ltc_dir)[0]
+ except OSError:
+ hwmon_node = "hwmon*"
+ else:
+ self.is_driver_initialized = True
+
self.HWMON_DIR = ltc_dir + hwmon_node + '/'
self.psu_voltage_reg = self.HWMON_DIR + "in1_input"
@@ -46,6 +56,8 @@ def __init__(self, psu_index):
# make it unique per Psu object
self._fan_list = []
+ self._fan_list.append(Fan(self.index, psu_fan=True, dependency=self))
+
def _get_cpld_register(self, reg_name):
# On successful read, returns the value read from given
# reg_name and on failure returns 'ERR'
@@ -70,6 +82,14 @@ def _get_i2c_register(self, reg_file):
# reg_name and on failure returns 'ERR'
rv = 'ERR'
+ if not self.is_driver_initialized:
+ reg_file_path = glob.glob(reg_file)
+ if len(reg_file_path):
+ reg_file = reg_file_path[0]
+ self._get_sysfs_path()
+ else:
+ return rv
+
if (not os.path.isfile(reg_file)):
return rv
@@ -83,6 +103,17 @@ def _get_i2c_register(self, reg_file):
rv = rv.lstrip(" ")
return rv
+ def _get_sysfs_path(self):
+ voltage_reg = glob.glob(self.psu_voltage_reg)
+ current_reg = glob.glob(self.psu_current_reg)
+ power_reg = glob.glob(self.psu_power_reg)
+
+ if len(voltage_reg) and len(current_reg) and len(power_reg):
+ self.psu_voltage_reg = voltage_reg_path[0]
+ self.psu_current_reg = current_reg_path[0]
+ self.psu_power_reg = power_reg_path[0]
+ self.is_driver_initialized = True
+
def get_name(self):
"""
Retrieves the name of the device
diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/thermal.py
index 70bac0c729d2..a54336d40f1c 100644
--- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/thermal.py
+++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/thermal.py
@@ -11,6 +11,7 @@
try:
import os
+ import glob
from sonic_platform_base.thermal_base import ThermalBase
from sonic_platform.psu import Psu
except ImportError as e:
@@ -36,13 +37,19 @@ class Thermal(ThermalBase):
def __init__(self, thermal_index):
self.index = thermal_index + 1
self.is_psu_thermal = False
+ self.is_driver_initialized = True
self.dependency = None
if self.index < 9:
i2c_path = self.I2C_DIR + self.I2C_DEV_MAPPING[self.index - 1][0]
hwmon_temp_index = self.I2C_DEV_MAPPING[self.index - 1][1]
hwmon_temp_suffix = "max"
- hwmon_node = os.listdir(i2c_path)[0]
+ try:
+ hwmon_node = os.listdir(i2c_path)[0]
+ except OSError:
+ hwmon_node = "hwmon*"
+ self.is_driver_initialized = False
+
self.HWMON_DIR = i2c_path + hwmon_node + '/'
if self.index == 4:
@@ -55,7 +62,12 @@ def __init__(self, thermal_index):
dev_path = "/sys/devices/platform/coretemp.0/hwmon/"
hwmon_temp_index = self.index - 7
hwmon_temp_suffix = "crit"
- hwmon_node = os.listdir(dev_path)[0]
+ try:
+ hwmon_node = os.listdir(dev_path)[0]
+ except OSError:
+ hwmon_node = "hwmon*"
+ self.is_driver_initialized = False
+
self.HWMON_DIR = dev_path + hwmon_node + '/'
self.thermal_temperature_file = self.HWMON_DIR \
@@ -70,6 +82,14 @@ def _read_sysfs_file(self, sysfs_file):
# sysfs_file and on failure returns 'ERR'
rv = 'ERR'
+ if not self.is_driver_initialized:
+ sysfs_file_path = glob.glob(sysfs_file)
+ if len(sysfs_file_path):
+ sysfs_file = sysfs_file_path[0]
+ self._get_sysfs_path()
+ else:
+ return rv
+
if (not os.path.isfile(sysfs_file)):
return rv
@@ -83,6 +103,19 @@ def _read_sysfs_file(self, sysfs_file):
rv = rv.lstrip(" ")
return rv
+ def _get_sysfs_path(self):
+ temperature_path = glob.glob(self.thermal_temperature_file)
+ high_threshold_path = glob.glob(self.thermal_high_threshold_file)
+ low_threshold_path = glob.glob(self.thermal_low_threshold_file)
+
+ if len(temperature_path) and len(high_threshold_path):
+ self.thermal_temperature_file = temperature_path[0]
+ self.thermal_high_threshold_file = high_threshold_path[0]
+ if len(low_threshold_path):
+ self.thermal_low_threshold_file = low_threshold_path
+
+ self.is_driver_initialized = True
+
def get_name(self):
"""
Retrieves the name of the thermal
diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/systemd/fancontrol.service b/platform/broadcom/sonic-platform-modules-dell/s6000/systemd/fancontrol.service
new file mode 100644
index 000000000000..75cc977b9935
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-dell/s6000/systemd/fancontrol.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Dell S6000 fan speed regulator
+After=platform-modules-s6000.service
+Before=pmon.service
+
+[Service]
+ExecStart=-/usr/local/bin/fancontrol.sh
+Restart=always
+RestartSec=30
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_sensors.py
index a0231bc507cf..b94b69388300 100755
--- a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_sensors.py
+++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_sensors.py
@@ -255,8 +255,8 @@ def print_psu(psu):
psu_fan_present = int(get_pmc_register('fan11_fault'))
input_voltage = float(get_pmc_register('in29_input')) / 1000
output_voltage = float(get_pmc_register('in30_input')) / 1000
- input_current = float(get_pmc_register('curr601_input')) / 100
- output_current = float(get_pmc_register('curr602_input')) / 100
+ input_current = float(get_pmc_register('curr601_input')) / 1000
+ output_current = float(get_pmc_register('curr602_input')) / 1000
input_power = float(get_pmc_register('power1_input')) / 1000000
output_power = float(get_pmc_register('power2_input')) / 1000000
if (input_power != 0):
@@ -268,8 +268,8 @@ def print_psu(psu):
psu_fan_present = int(get_pmc_register('fan12_fault'))
input_voltage = float(get_pmc_register('in31_input')) / 1000
output_voltage = float(get_pmc_register('in32_input')) / 1000
- input_current = float(get_pmc_register('curr701_input')) / 100
- output_current = float(get_pmc_register('curr702_input')) / 100
+ input_current = float(get_pmc_register('curr701_input')) / 1000
+ output_current = float(get_pmc_register('curr702_input')) / 1000
input_power = float(get_pmc_register('power3_input')) / 1000000
output_power = float(get_pmc_register('power4_input')) / 1000000
if (input_power != 0):
diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_platform.sh b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_platform.sh
index d8b13ca02c1e..8533d9a198e2 100755
--- a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_platform.sh
+++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_platform.sh
@@ -54,6 +54,26 @@ sys_eeprom() {
esac
}
+#Attach/Detach eeprom on each IOM
+switch_board_eeprom() {
+ case $1 in
+ "new_device")
+ for ((i=14;i<=17;i++));
+ do
+ i2c_config "echo 24c02 0x50 > /sys/bus/i2c/devices/i2c-$i/$1"
+ done
+ ;;
+ "delete_device")
+ for ((i=14;i<=17;i++));
+ do
+ i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1"
+ done
+ ;;
+ *) echo "s6100_platform: switch_board_eeprom : invalid command !"
+ ;;
+ esac
+}
+
#Attach/Detach CPLD devices to drivers for each IOM
switch_board_cpld() {
case $1 in
@@ -245,7 +265,7 @@ install_python_api_package() {
remove_python_api_package() {
rv=$(pip show sonic-platform > /dev/null 2>/dev/null)
if [ $? -eq 0 ]; then
- rv = $(pip uninstall -y sonic-platform > /dev/null 2>/dev/null)
+ rv=$(pip uninstall -y sonic-platform > /dev/null 2>/dev/null)
fi
}
@@ -267,6 +287,7 @@ if [[ "$1" == "init" ]]; then
cpu_board_mux "new_device"
switch_board_mux "new_device"
sys_eeprom "new_device"
+ switch_board_eeprom "new_device"
switch_board_cpld "new_device"
switch_board_qsfp_mux "new_device"
switch_board_sfp "new_device"
@@ -280,6 +301,7 @@ elif [[ "$1" == "deinit" ]]; then
xcvr_presence_interrupts "disable"
switch_board_sfp "delete_device"
switch_board_cpld "delete_device"
+ switch_board_eeprom "delete_device"
switch_board_mux "delete_device"
sys_eeprom "delete_device"
switch_board_qsfp "delete_device"
diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py
index e39e8480e2c7..ec1848fc8dca 100755
--- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py
+++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py
@@ -54,10 +54,11 @@ def __init__(self):
ChassisBase.__init__(self)
# Initialize EEPROM
- self.sys_eeprom = Eeprom()
+ self._eeprom = Eeprom()
for i in range(MAX_S6100_MODULE):
module = Module(i)
self._module_list.append(module)
+ self._sfp_list.extend(module._sfp_list)
for i in range(MAX_S6100_FAN):
fan = Fan(i)
@@ -107,7 +108,7 @@ def get_name(self):
Returns:
string: The name of the chassis
"""
- return self.sys_eeprom.modelstr()
+ return self._eeprom.modelstr()
def get_presence(self):
"""
@@ -123,7 +124,7 @@ def get_model(self):
Returns:
string: Model/part number of chassis
"""
- return self.sys_eeprom.part_number_str()
+ return self._eeprom.part_number_str()
def get_serial(self):
"""
@@ -131,7 +132,7 @@ def get_serial(self):
Returns:
string: Serial number of chassis
"""
- return self.sys_eeprom.serial_str()
+ return self._eeprom.serial_str()
def get_status(self):
"""
@@ -150,7 +151,7 @@ def get_base_mac(self):
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
- return self.sys_eeprom.base_mac_addr()
+ return self._eeprom.base_mac_addr()
def get_serial_number(self):
"""
@@ -160,7 +161,7 @@ def get_serial_number(self):
A string containing the hardware serial number for this
chassis.
"""
- return self.sys_eeprom.serial_number_str()
+ return self._eeprom.serial_number_str()
def get_system_eeprom_info(self):
"""
@@ -170,7 +171,7 @@ def get_system_eeprom_info(self):
OCP ONIE TlvInfo EEPROM format and values are their corresponding
values.
"""
- return self.sys_eeprom.system_eeprom_info()
+ return self._eeprom.system_eeprom_info()
def get_reboot_cause(self):
"""
diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/eeprom.py
index 4e683e1e511b..8bd900b6c26b 100644
--- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/eeprom.py
+++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/eeprom.py
@@ -18,15 +18,26 @@
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
- def __init__(self):
- self.eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0050/eeprom"
+ def __init__(self, i2c_line=0, iom_eeprom=False):
+ self.is_module = iom_eeprom
+ if self.is_module:
+ self.eeprom_path = ("/sys/class/i2c-adapter"
+ "/i2c-{0}/{0}-0050/eeprom").format(i2c_line)
+ else:
+ self.eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0050/eeprom"
super(Eeprom, self).__init__(self.eeprom_path, 0, '', True)
self.eeprom_tlv_dict = dict()
+
try:
- self.eeprom_data = self.read_eeprom()
+ if self.is_module:
+ self.write_eeprom("\x00\x00")
+ self.eeprom_data = self.read_eeprom_bytes(256)
+ else:
+ self.eeprom_data = self.read_eeprom()
except:
self.eeprom_data = "N/A"
- raise RuntimeError("Eeprom is not Programmed")
+ if not self.is_module:
+ raise RuntimeError("Eeprom is not Programmed")
else:
eeprom = self.eeprom_data
@@ -76,8 +87,12 @@ def base_mac_addr(self):
return ":".join([binascii.b2a_hex(T) for T in results[2]])
def modelstr(self):
- (is_valid, results) = self.get_tlv_field(
- self.eeprom_data, self._TLV_CODE_PRODUCT_NAME)
+ if self.is_module:
+ (is_valid, results) = self.get_tlv_field(
+ self.eeprom_data, self._TLV_CODE_PLATFORM_NAME)
+ else:
+ (is_valid, results) = self.get_tlv_field(
+ self.eeprom_data, self._TLV_CODE_PRODUCT_NAME)
if not is_valid:
return "N/A"
diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan.py
index 2aef71b756e7..49e95357b6f1 100644
--- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan.py
+++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan.py
@@ -33,6 +33,10 @@ def __init__(self, fantray_index=1, fan_index=1, psu_fan=False):
# from 1
self.fantrayindex = fantray_index + 1
self.fanindex = fan_index + 1
+ self.fan_presence_reg = "fan{}_fault".format(
+ 2 * self.fantrayindex - 1)
+ self.fan_status_reg = "fan{}_alarm".format(
+ 2 * self.fantrayindex - 1)
self.get_fan_speed_reg = "fan{}_input".format(
2 * self.fantrayindex - 1)
self.get_fan_dir_reg = "fan{}_airflow".format(
@@ -43,7 +47,9 @@ def __init__(self, fantray_index=1, fan_index=1, psu_fan=False):
else:
# PSU Fan index starts from 11
self.fanindex = fan_index + 10
+ self.fan_presence_reg = "fan{}_fault".format(self.fanindex)
self.get_fan_speed_reg = "fan{}_input".format(self.fanindex)
+ self.get_fan_dir_reg = "fan{}_airflow".format(self.fanindex)
self.max_fan_speed = MAX_S6100_PSU_FAN_SPEED
def _get_pmc_register(self, reg_name):
@@ -84,6 +90,9 @@ def get_model(self):
"""
# For Serial number "US-01234D-54321-25A-0123-A00", the part
# number is "01234D"
+ if self.is_psu_fan:
+ return 'NA'
+
fan_serialno = self._get_pmc_register(self.fan_serialno_reg)
if (fan_serialno != 'ERR') and self.get_presence():
if (len(fan_serialno.split('-')) > 1):
@@ -102,6 +111,9 @@ def get_serial(self):
string: Serial number of FAN
"""
# Sample Serial number format "US-01234D-54321-25A-0123-A00"
+ if self.is_psu_fan:
+ return 'NA'
+
fan_serialno = self._get_pmc_register(self.fan_serialno_reg)
if (fan_serialno == 'ERR') or not self.get_presence():
fan_serialno = 'NA'
@@ -115,11 +127,11 @@ def get_presence(self):
bool: True if fan is present, False if not
"""
status = False
- fantray_presence = self._get_pmc_register(self.get_fan_speed_reg)
+ fantray_presence = self._get_pmc_register(self.fan_presence_reg)
if (fantray_presence != 'ERR'):
fantray_presence = int(fantray_presence, 10)
- if (fantray_presence > 0):
- status = True
+ if (~fantray_presence & 0b1):
+ status = True
return status
@@ -130,11 +142,18 @@ def get_status(self):
bool: True if FAN is operating properly, False if not
"""
status = False
- fantray_status = self._get_pmc_register(self.get_fan_speed_reg)
- if (fantray_status != 'ERR'):
- fantray_status = int(fantray_status, 10)
- if (fantray_status > 5000):
- status = True
+ if self.is_psu_fan:
+ fantray_status = self._get_pmc_register(self.get_fan_speed_reg)
+ if (fantray_status != 'ERR'):
+ fantray_status = int(fantray_status, 10)
+ if (fantray_status > 1000):
+ status = True
+ else:
+ fantray_status = self._get_pmc_register(self.fan_status_reg)
+ if (fantray_status != 'ERR'):
+ fantray_status = int(fantray_status, 10)
+ if (~fantray_status & 0b1):
+ status = True
return status
@@ -144,13 +163,18 @@ def get_direction(self):
Returns:
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
depending on fan direction
+
+ Notes:
+ In DellEMC platforms,
+ - Forward/Exhaust : Air flows from Port side to Fan side.
+ - Reverse/Intake : Air flows from Fan side to Port side.
"""
- direction = ['FAN_DIRECTION_INTAKE', 'FAN_DIRECTION_EXHAUST']
+ direction = [self.FAN_DIRECTION_INTAKE, self.FAN_DIRECTION_EXHAUST]
fan_direction = self._get_pmc_register(self.get_fan_dir_reg)
if (fan_direction != 'ERR') and self.get_presence():
fan_direction = int(fan_direction, 10)
else:
- return 'N/A'
+ return self.FAN_DIRECTION_NOT_APPLICABLE
return direction[fan_direction]
def get_speed(self):
@@ -216,10 +240,17 @@ def get_status_led(self):
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings.
"""
- if self.get_status():
- return self.STATUS_LED_COLOR_GREEN
+ if self.is_psu_fan:
+ # No LED available for PSU Fan
+ return None
else:
- return self.STATUS_LED_COLOR_OFF
+ if self.get_presence():
+ if self.get_status():
+ return self.STATUS_LED_COLOR_GREEN
+ else:
+ return self.STATUS_LED_COLOR_AMBER
+ else:
+ return self.STATUS_LED_COLOR_OFF
def get_target_speed(self):
"""
diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/module.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/module.py
index 265dc206ad0c..19198098dfd7 100644
--- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/module.py
+++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/module.py
@@ -14,6 +14,7 @@
from sonic_platform_base.module_base import ModuleBase
from sonic_platform.sfp import Sfp
from sonic_platform.component import Component
+ from sonic_platform.eeprom import Eeprom
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
@@ -55,7 +56,7 @@ def __init__(self, module_index):
self.port_start = (self.index - 1) * 16
self.port_end = (self.index * 16) - 1
self.port_i2c_line = self.IOM_I2C_MAPPING[self.index]
- self.eeprom_tlv_dict = dict()
+ self._eeprom = Eeprom(iom_eeprom=True, i2c_line=self.port_i2c_line)
self.iom_status_reg = "iom_status"
self.iom_presence_reg = "iom_presence"
@@ -108,7 +109,7 @@ def get_name(self):
Returns:
string: The name of the device
"""
- return "IOM{}: 16xQSFP+".format(self.index)
+ return "IOM{}: {}".format(self.index, self._eeprom.modelstr())
def get_presence(self):
"""
@@ -133,7 +134,7 @@ def get_model(self):
Returns:
string: part number of module
"""
- return 'NA'
+ return self._eeprom.part_number_str()
def get_serial(self):
"""
@@ -142,7 +143,7 @@ def get_serial(self):
Returns:
string: Serial number of module
"""
- return 'NA'
+ return self._eeprom.serial_str()
def get_status(self):
"""
@@ -178,7 +179,7 @@ def get_serial_number(self):
Returns:
A string containing the hardware serial number for this module.
"""
- return 'NA'
+ return self._eeprom.serial_number_str()
def get_system_eeprom_info(self):
"""
@@ -192,4 +193,4 @@ def get_system_eeprom_info(self):
‘0x24’:’001c0f000fcd0a’, ‘0x25’:’02/03/2018 16:22:00’,
‘0x26’:’01’, ‘0x27’:’REV01’, ‘0x28’:’AG9064-C2358-16G’}
"""
- return self.eeprom_tlv_dict
+ return self._eeprom.system_eeprom_info()
diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/platform_sensors.py
index 76e527e13d73..05cbb3a1a4c1 100755
--- a/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/platform_sensors.py
+++ b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/platform_sensors.py
@@ -262,8 +262,8 @@ def print_psu(psu):
psu_fan_present = int(get_pmc_register('fan11_fault'))
input_voltage = float(get_pmc_register('in29_input')) / 1000
output_voltage = float(get_pmc_register('in30_input')) / 1000
- input_current = float(get_pmc_register('curr601_input')) / 100
- output_current = float(get_pmc_register('curr602_input')) /100
+ input_current = float(get_pmc_register('curr601_input')) / 1000
+ output_current = float(get_pmc_register('curr602_input')) / 1000
input_power = float(get_pmc_register('power1_input')) / 1000000
output_power = float(get_pmc_register('power2_input')) / 1000000
if (input_power != 0):
@@ -275,8 +275,8 @@ def print_psu(psu):
psu_fan_present = int(get_pmc_register('fan12_fault'))
input_voltage = float(get_pmc_register('in31_input')) / 1000
output_voltage = float(get_pmc_register('in32_input')) / 1000
- input_current = float(get_pmc_register('curr701_input')) / 100
- output_current = float(get_pmc_register('curr702_input')) / 100
+ input_current = float(get_pmc_register('curr701_input')) / 1000
+ output_current = float(get_pmc_register('curr702_input')) / 1000
input_power = float(get_pmc_register('power3_input')) / 1000000
output_power = float(get_pmc_register('power4_input')) / 1000000
if (input_power != 0):
diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py
index 3472bb3e7fb0..3e070d54004e 100755
--- a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py
+++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py
@@ -73,6 +73,7 @@ class Chassis(ChassisBase):
power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED
def __init__(self):
+ ChassisBase.__init__(self)
PORT_START = 0
PORT_END = 31
PORTS_IN_BLOCK = (PORT_END + 1)
@@ -92,9 +93,8 @@ def __init__(self):
self.PORT_I2C_MAPPING[index][1])
self._sfp_list.append(sfp_node)
- ChassisBase.__init__(self)
# Initialize EEPROM
- self.sys_eeprom = Eeprom()
+ self._eeprom = Eeprom()
for i in range(MAX_Z9100_FANTRAY):
for j in range(MAX_Z9100_FAN):
fan = Fan(i, j)
@@ -137,7 +137,7 @@ def get_name(self):
Returns:
string: The name of the chassis
"""
- return self.sys_eeprom.modelstr()
+ return self._eeprom.modelstr()
def get_presence(self):
"""
@@ -153,7 +153,7 @@ def get_model(self):
Returns:
string: Model/part number of chassis
"""
- return self.sys_eeprom.part_number_str()
+ return self._eeprom.part_number_str()
def get_serial(self):
"""
@@ -161,7 +161,29 @@ def get_serial(self):
Returns:
string: Serial number of chassis
"""
- return self.sys_eeprom.serial_str()
+ return self._eeprom.serial_str()
+
+ def get_sfp(self, index):
+ """
+ Retrieves sfp represented by (1-based) index
+
+ Args:
+ index: An integer, the index (1-based) of the sfp to retrieve.
+ The index should be the sequence of a physical port in a chassis,
+ starting from 1.
+ For example, 0 for Ethernet0, 1 for Ethernet4 and so on.
+
+ Returns:
+ An object dervied from SfpBase representing the specified sfp
+ """
+ sfp = None
+
+ try:
+ sfp = self._sfp_list[index-1]
+ except IndexError:
+ sys.stderr.write("SFP index {} out of range (1-{})\n".format(
+ index, len(self._sfp_list)-1))
+ return sfp
def get_status(self):
"""
@@ -180,7 +202,7 @@ def get_base_mac(self):
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
- return self.sys_eeprom.base_mac_addr()
+ return self._eeprom.base_mac_addr()
def get_serial_number(self):
"""
@@ -189,7 +211,7 @@ def get_serial_number(self):
Returns:
A string containing the hardware serial number for this chassis.
"""
- return self.sys_eeprom.serial_number_str()
+ return self._eeprom.serial_number_str()
def get_system_eeprom_info(self):
"""
@@ -200,7 +222,7 @@ def get_system_eeprom_info(self):
OCP ONIE TlvInfo EEPROM format and values are their corresponding
values.
"""
- return self.sys_eeprom.system_eeprom_info()
+ return self._eeprom.system_eeprom_info()
def get_reboot_cause(self):
"""
diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan.py
index ae3c5e9fbcab..6ff688fa3a1e 100755
--- a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan.py
+++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan.py
@@ -33,6 +33,10 @@ def __init__(self, fantray_index=1, fan_index=1, psu_fan=False):
# from 1
self.fantrayindex = fantray_index + 1
self.fanindex = fan_index + 1
+ self.fan_presence_reg = "fan{}_fault".format(
+ 2 * (self.fantrayindex - 1) + (self.fanindex - 1) + 1 )
+ self.fan_status_reg = "fan{}_alarm".format(
+ 2 * (self.fantrayindex - 1) + (self.fanindex - 1) + 1 )
self.get_fan_speed_reg = "fan{}_input".format(
2 * (self.fantrayindex - 1) + (self.fanindex - 1) + 1 )
self.get_fan_dir_reg = "fan{}_airflow".format(
@@ -43,7 +47,9 @@ def __init__(self, fantray_index=1, fan_index=1, psu_fan=False):
else:
# PSU Fan index starts from 11
self.fanindex = fan_index + 10
+ self.fan_presence_reg = "fan{}_fault".format(self.fanindex)
self.get_fan_speed_reg = "fan{}_input".format(self.fanindex)
+ self.get_fan_dir_reg = "fan{}_airflow".format(self.fanindex)
self.max_fan_speed = MAX_Z9100_PSU_FAN_SPEED
def _get_pmc_register(self, reg_name):
@@ -83,6 +89,9 @@ def get_model(self):
"""
# For Serial number "US-01234D-54321-25A-0123-A00", the part
# number is "01234D"
+ if self.is_psu_fan:
+ return 'NA'
+
fan_serialno = self._get_pmc_register(self.fan_serialno_reg)
if (fan_serialno != 'ERR') and self.get_presence():
if (len(fan_serialno.split('-')) > 1):
@@ -101,6 +110,9 @@ def get_serial(self):
string: Serial number of FAN
"""
# Sample Serial number format "US-01234D-54321-25A-0123-A00"
+ if self.is_psu_fan:
+ return 'NA'
+
fan_serialno = self._get_pmc_register(self.fan_serialno_reg)
if (fan_serialno == 'ERR') or not self.get_presence():
fan_serialno = 'NA'
@@ -114,11 +126,11 @@ def get_presence(self):
bool: True if fan is present, False if not
"""
status = False
- fantray_presence = self._get_pmc_register(self.get_fan_speed_reg)
+ fantray_presence = self._get_pmc_register(self.fan_presence_reg)
if (fantray_presence != 'ERR'):
fantray_presence = int(fantray_presence, 10)
- if (fantray_presence > 0):
- status = True
+ if (~fantray_presence & 0b1):
+ status = True
return status
@@ -129,11 +141,18 @@ def get_status(self):
bool: True if FAN is operating properly, False if not
"""
status = False
- fantray_status = self._get_pmc_register(self.get_fan_speed_reg)
- if (fantray_status != 'ERR'):
- fantray_status = int(fantray_status, 10)
- if (fantray_status > 5000):
- status = True
+ if self.is_psu_fan:
+ fantray_status = self._get_pmc_register(self.get_fan_speed_reg)
+ if (fantray_status != 'ERR'):
+ fantray_status = int(fantray_status, 10)
+ if (fantray_status > 1000):
+ status = True
+ else:
+ fantray_status = self._get_pmc_register(self.fan_status_reg)
+ if (fantray_status != 'ERR'):
+ fantray_status = int(fantray_status, 10)
+ if (~fantray_status & 0b1):
+ status = True
return status
@@ -143,13 +162,18 @@ def get_direction(self):
Returns:
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
depending on fan direction
+
+ Notes:
+ In DellEMC platforms,
+ - Forward/Exhaust : Air flows from Port side to Fan side.
+ - Reverse/Intake : Air flows from Fan side to Port side.
"""
- direction = ['FAN_DIRECTION_INTAKE', 'FAN_DIRECTION_EXHAUST']
+ direction = [self.FAN_DIRECTION_INTAKE, self.FAN_DIRECTION_EXHAUST]
fan_direction = self._get_pmc_register(self.get_fan_dir_reg)
if (fan_direction != 'ERR') and self.get_presence():
fan_direction = int(fan_direction, 10)
else:
- return 'N/A'
+ return self.FAN_DIRECTION_NOT_APPLICABLE
return direction[fan_direction]
def get_speed(self):
@@ -215,10 +239,17 @@ def get_status_led(self):
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings.
"""
- if self.get_status():
- return self.STATUS_LED_COLOR_GREEN
+ if self.is_psu_fan:
+ # No LED available for PSU Fan
+ return None
else:
- return self.STATUS_LED_COLOR_OFF
+ if self.get_presence():
+ if self.get_status():
+ return self.STATUS_LED_COLOR_GREEN
+ else:
+ return self.STATUS_LED_COLOR_AMBER
+ else:
+ return self.STATUS_LED_COLOR_OFF
def get_target_speed(self):
"""
diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/control b/platform/broadcom/sonic-platform-modules-delta/debian/control
index 65b01234b4ec..e2e9883f9b2b 100644
--- a/platform/broadcom/sonic-platform-modules-delta/debian/control
+++ b/platform/broadcom/sonic-platform-modules-delta/debian/control
@@ -7,25 +7,25 @@ Standards-Version: 3.9.3
Package: platform-modules-ag9032v1
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: platform-modules-ag9064
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: platform-modules-ag5648
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: platform-modules-et-6248brb
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: platform-modules-ag9032v2a
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as syseeprom, sfp
diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.init b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.init
index 64361ced6b6c..58681208ef6c 100755
--- a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.init
+++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.init
@@ -25,7 +25,7 @@ start)
modprobe dni_gpio
modprobe delta_et-6248brb_platform
- if [ `uname -a | awk '{print $3}'` = "4.9.0-9-2-amd64" ]; then
+ if [ `uname -a | awk '{print $3}'` = "4.9.0-11-2-amd64" ]; then
echo "453" > "/sys/class/gpio/export"
echo "454" > "/sys/class/gpio/export"
echo "455" > "/sys/class/gpio/export"
diff --git a/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/led_status.sh b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/led_status.sh
index 734a44a6ca95..573af2156661 100644
--- a/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/led_status.sh
+++ b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/led_status.sh
@@ -7,7 +7,7 @@ FAN2_RPM="/sys/bus/i2c/devices/0-002e/fan2_input"
FAN_TRAY1_LED="/sys/devices/platform/delta-et6248brb-gpio.0/FAN/fan1_led_ag"
FAN_TRAY2_LED="/sys/devices/platform/delta-et6248brb-gpio.0/FAN/fan2_led_ag"
-if [ `uname -a | awk '{print $3}'` = "4.9.0-9-2-amd64" ]; then
+if [ `uname -a | awk '{print $3}'` = "4.9.0-11-2-amd64" ]; then
SYS_LED_G="/sys/class/gpio/gpio453/value"
SYS_LED_R="/sys/class/gpio/gpio454/value"
PWR_LED_G="/sys/class/gpio/gpio455/value"
diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/qsfp_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/qsfp_monitor.sh
index 249f179216a6..7776493bc20a 100755
--- a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/qsfp_monitor.sh
+++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/qsfp_monitor.sh
@@ -65,7 +65,7 @@ function _docker_swss_check {
while true
do
# Check if syncd starts
- result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME
+ result=`sonic-db-cli ASIC_DB HLEN HIDDEN`
if [ "$result" == "3" ]; then
return
fi
diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_monitor.sh
index 7f50d137bcb7..0a4ba20ab767 100644
--- a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_monitor.sh
+++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_monitor.sh
@@ -67,7 +67,7 @@ function _docker_swss_check {
while true
do
# Check if syncd starts
- result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME
+ result=`sonic-db-cli ASIC_DB HLEN HIDDEN`
if [ "$result" == "3" ]; then
return
fi
diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_monitor.sh
index 36f9e53ef108..b3192f2efb7a 100644
--- a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_monitor.sh
+++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_monitor.sh
@@ -67,7 +67,7 @@ function _docker_swss_check {
while true
do
# Check if syncd starts
- result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME
+ result=`sonic-db-cli ASIC_DB HLEN HIDDEN`
if [ "$result" == "3" ]; then
return
fi
diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_monitor.sh
index 249f179216a6..7776493bc20a 100755
--- a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_monitor.sh
+++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_monitor.sh
@@ -65,7 +65,7 @@ function _docker_swss_check {
while true
do
# Check if syncd starts
- result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME
+ result=`sonic-db-cli ASIC_DB HLEN HIDDEN`
if [ "$result" == "3" ]; then
return
fi
diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_monitor.sh
index 51c49c1152f5..47cfbb3ea008 100755
--- a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_monitor.sh
+++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_monitor.sh
@@ -66,7 +66,7 @@ function _docker_swss_check {
while true
do
# Check if syncd starts
- result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME
+ result=`sonic-db-cli ASIC_DB HLEN HIDDEN`
if [ "$result" == "3" ]; then
return
fi
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/utils/inventec_d6356_util.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/utils/inventec_d6356_util.py
index 890973cb8356..10fcb001b0c2 100755
--- a/platform/broadcom/sonic-platform-modules-inventec/d6356/utils/inventec_d6356_util.py
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/utils/inventec_d6356_util.py
@@ -141,7 +141,7 @@ def system_install():
status, output = exec_cmd("rmmod lpc_ich ", 1)
#insert extra module
- status, output = exec_cmd("insmod /lib/modules/4.9.0-9-2-amd64/kernel/drivers/gpio/gpio-ich.ko gpiobase=0",1)
+ status, output = exec_cmd("insmod /lib/modules/4.9.0-11-2-amd64/kernel/drivers/gpio/gpio-ich.ko gpiobase=0",1)
#install drivers
for i in range(0,len(drivers)):
diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/control b/platform/broadcom/sonic-platform-modules-inventec/debian/control
index 6cb61630823f..86f7e7b20f65 100644
--- a/platform/broadcom/sonic-platform-modules-inventec/debian/control
+++ b/platform/broadcom/sonic-platform-modules-inventec/debian/control
@@ -7,30 +7,30 @@ Standards-Version: 3.9.3
Package: platform-modules-d7032q28b
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led
Package: platform-modules-d7054q28b
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led
Package: platform-modules-d6254qs
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led
Package: platform-modules-d6556
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led
Package: platform-modules-d6356
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led
Package: platform-modules-d7264q28b
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_monitor.py b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_monitor.py
index d225400121b8..ec83499c5c7b 100755
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_monitor.py
+++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_monitor.py
@@ -468,7 +468,7 @@ def __init__(self, log_file, log_level):
masterLED_file = open(MASTER_LED_PATH, 'r+')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
- return False
+ return
masterLED_file.write(str(master_led_value))
masterLED_file.close()
@@ -477,10 +477,9 @@ def __init__(self, log_file, log_level):
systemLED_file = open(SYSTEM_LED_PATH, 'r+')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
- return False
+ return
systemLED_file.write(str(system_led_value))
systemLED_file.close()
- pass
def manage_device(self):
thermal = QFX5210_ThermalUtil()
diff --git a/platform/broadcom/sonic-platform-modules-quanta/debian/rules b/platform/broadcom/sonic-platform-modules-quanta/debian/rules
old mode 100644
new mode 100755
diff --git a/platform/cavium/docker-syncd-cavm-rpc.mk b/platform/cavium/docker-syncd-cavm-rpc.mk
index e57370fce5ca..ebe614b3c183 100644
--- a/platform/cavium/docker-syncd-cavm-rpc.mk
+++ b/platform/cavium/docker-syncd-cavm-rpc.mk
@@ -2,7 +2,7 @@
DOCKER_SYNCD_CAVM_RPC = docker-syncd-cavm-rpc.gz
$(DOCKER_SYNCD_CAVM_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-cavm-rpc
-$(DOCKER_SYNCD_CAVM_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(CAVM_LIBSAI) $(XP_TOOLS) $(REDIS_TOOLS)
+$(DOCKER_SYNCD_CAVM_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(CAVM_LIBSAI) $(XP_TOOLS) $(REDIS_TOOLS) $(PTF)
$(DOCKER_SYNCD_CAVM_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)
ifeq ($(INSTALL_DEBUG_TOOLS), y)
$(DOCKER_SYNCD_CAVM_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \
diff --git a/platform/cavium/docker-syncd-cavm.mk b/platform/cavium/docker-syncd-cavm.mk
index a136828dbff1..ad43d6f1196f 100644
--- a/platform/cavium/docker-syncd-cavm.mk
+++ b/platform/cavium/docker-syncd-cavm.mk
@@ -20,3 +20,4 @@ $(DOCKER_SYNCD_CAVM)_CONTAINER_NAME = syncd
$(DOCKER_SYNCD_CAVM)_RUN_OPT += --net=host --privileged -t
$(DOCKER_SYNCD_CAVM)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf
$(DOCKER_SYNCD_CAVM)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro
+$(DOCKER_SYNCD_CAVM)_BASE_IMAGE_FILES += monit_syncd:/etc/monit/conf.d
diff --git a/platform/cavium/docker-syncd-cavm/base_image_files/monit_syncd b/platform/cavium/docker-syncd-cavm/base_image_files/monit_syncd
new file mode 100644
index 000000000000..3079618990ed
--- /dev/null
+++ b/platform/cavium/docker-syncd-cavm/base_image_files/monit_syncd
@@ -0,0 +1,7 @@
+###############################################################################
+## Monit configuration for syncd container
+## process list:
+## syncd
+###############################################################################
+check process syncd matching "/usr/bin/syncd"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/platform/cavium/docker-syncd-cavm/supervisord.conf b/platform/cavium/docker-syncd-cavm/supervisord.conf
index c823ab5680ef..0c6285d46ae0 100644
--- a/platform/cavium/docker-syncd-cavm/supervisord.conf
+++ b/platform/cavium/docker-syncd-cavm/supervisord.conf
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name syncd
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
diff --git a/platform/centec/docker-syncd-centec-rpc.mk b/platform/centec/docker-syncd-centec-rpc.mk
index 71c8ef7753c1..47c672dd93de 100644
--- a/platform/centec/docker-syncd-centec-rpc.mk
+++ b/platform/centec/docker-syncd-centec-rpc.mk
@@ -2,7 +2,7 @@
DOCKER_SYNCD_CENTEC_RPC = docker-syncd-centec-rpc.gz
$(DOCKER_SYNCD_CENTEC_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-centec-rpc
-$(DOCKER_SYNCD_CENTEC_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT)
+$(DOCKER_SYNCD_CENTEC_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(PTF)
$(DOCKER_SYNCD_CENTEC_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)
ifeq ($(INSTALL_DEBUG_TOOLS), y)
$(DOCKER_SYNCD_CENTEC_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \
diff --git a/platform/centec/docker-syncd-centec.mk b/platform/centec/docker-syncd-centec.mk
index 360690731a58..a0dbcc629dee 100644
--- a/platform/centec/docker-syncd-centec.mk
+++ b/platform/centec/docker-syncd-centec.mk
@@ -21,3 +21,4 @@ $(DOCKER_SYNCD_CENTEC)_RUN_OPT += --net=host --privileged -t
$(DOCKER_SYNCD_CENTEC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf
$(DOCKER_SYNCD_CENTEC)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd
$(DOCKER_SYNCD_CENTEC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro
+$(DOCKER_SYNCD_CENTEC)_BASE_IMAGE_FILES += monit_syncd:/etc/monit/conf.d
diff --git a/platform/centec/docker-syncd-centec/base_image_files/monit_syncd b/platform/centec/docker-syncd-centec/base_image_files/monit_syncd
new file mode 100644
index 000000000000..3079618990ed
--- /dev/null
+++ b/platform/centec/docker-syncd-centec/base_image_files/monit_syncd
@@ -0,0 +1,7 @@
+###############################################################################
+## Monit configuration for syncd container
+## process list:
+## syncd
+###############################################################################
+check process syncd matching "/usr/bin/syncd"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/platform/centec/docker-syncd-centec/supervisord.conf b/platform/centec/docker-syncd-centec/supervisord.conf
index c823ab5680ef..0c6285d46ae0 100644
--- a/platform/centec/docker-syncd-centec/supervisord.conf
+++ b/platform/centec/docker-syncd-centec/supervisord.conf
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name syncd
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
diff --git a/platform/centec/sonic-platform-modules-e582/debian/control b/platform/centec/sonic-platform-modules-e582/debian/control
index ba30e04f0388..c449246b2823 100644
--- a/platform/centec/sonic-platform-modules-e582/debian/control
+++ b/platform/centec/sonic-platform-modules-e582/debian/control
@@ -7,11 +7,11 @@ Standards-Version: 3.9.3
Package: platform-modules-e582-48x2q4z
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: platform-modules-e582-48x6q
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
diff --git a/platform/innovium/docker-syncd-invm-rpc.mk b/platform/innovium/docker-syncd-invm-rpc.mk
index 313f0d12ac20..62d6891bbc21 100755
--- a/platform/innovium/docker-syncd-invm-rpc.mk
+++ b/platform/innovium/docker-syncd-invm-rpc.mk
@@ -2,7 +2,7 @@
DOCKER_SYNCD_INVM_RPC = docker-syncd-invm-rpc.gz
$(DOCKER_SYNCD_INVM_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-invm-rpc
-$(DOCKER_SYNCD_INVM_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(INVM_LIBSAI)
+$(DOCKER_SYNCD_INVM_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(INVM_LIBSAI) $(PTF)
$(DOCKER_SYNCD_INVM_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BASE)
SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_INVM_RPC)
ifeq ($(ENABLE_SYNCD_RPC),y)
diff --git a/platform/innovium/invm-sai.mk b/platform/innovium/invm-sai.mk
index 8c236a8b68d2..2d89ef71e3b4 100755
--- a/platform/innovium/invm-sai.mk
+++ b/platform/innovium/invm-sai.mk
@@ -1,6 +1,6 @@
# INVM SAI
-INVM_SAI_ONLINE = https://github.com/Innovium/SONiC/raw/master/debian/master
+INVM_SAI_ONLINE = https://github.com/Innovium/SONiC/raw/master/debian/201911
INVM_LIBSAI = isai.deb
INVM_HSAI = saihdr.deb
diff --git a/platform/innovium/sonic-platform-modules-cel/debian/control b/platform/innovium/sonic-platform-modules-cel/debian/control
index 48ef777a99a6..543d381ab6f7 100755
--- a/platform/innovium/sonic-platform-modules-cel/debian/control
+++ b/platform/innovium/sonic-platform-modules-cel/debian/control
@@ -7,5 +7,5 @@ Standards-Version: 3.9.3
Package: platform-modules-midstone-200i
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices
diff --git a/platform/innovium/sonic-platform-modules-delta/debian/control b/platform/innovium/sonic-platform-modules-delta/debian/control
index 71c403387f80..3fe3ffc9f526 100644
--- a/platform/innovium/sonic-platform-modules-delta/debian/control
+++ b/platform/innovium/sonic-platform-modules-delta/debian/control
@@ -7,7 +7,7 @@ Standards-Version: 3.9.3
Package: platform-modules-et-c032if
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
diff --git a/platform/marvell-arm64/docker-syncd-mrvl-rpc.mk b/platform/marvell-arm64/docker-syncd-mrvl-rpc.mk
index 0e1b65f2fd5d..c3ce6c10119c 100644
--- a/platform/marvell-arm64/docker-syncd-mrvl-rpc.mk
+++ b/platform/marvell-arm64/docker-syncd-mrvl-rpc.mk
@@ -2,7 +2,7 @@
DOCKER_SYNCD_MRVL_RPC = docker-syncd-mrvl-rpc.gz
$(DOCKER_SYNCD_MRVL_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-mrvl-rpc
-$(DOCKER_SYNCD_MRVL_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT)
+$(DOCKER_SYNCD_MRVL_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(PTF)
$(DOCKER_SYNCD_MRVL_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)
ifeq ($(INSTALL_DEBUG_TOOLS), y)
$(DOCKER_SYNCD_MRVL_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \
diff --git a/platform/marvell-arm64/docker-syncd-mrvl.mk b/platform/marvell-arm64/docker-syncd-mrvl.mk
index e00769a59700..841e3b4b165f 100644
--- a/platform/marvell-arm64/docker-syncd-mrvl.mk
+++ b/platform/marvell-arm64/docker-syncd-mrvl.mk
@@ -11,3 +11,4 @@ $(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \
$(LIBSAIREDIS_DBG)
$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /host/warmboot:/var/warmboot
+$(DOCKER_SYNCD_BASE)_BASE_IMAGE_FILES += monit_syncd:/etc/monit/conf.d
diff --git a/platform/marvell-arm64/docker-syncd-mrvl/base_image_files/monit_syncd b/platform/marvell-arm64/docker-syncd-mrvl/base_image_files/monit_syncd
new file mode 100644
index 000000000000..3079618990ed
--- /dev/null
+++ b/platform/marvell-arm64/docker-syncd-mrvl/base_image_files/monit_syncd
@@ -0,0 +1,7 @@
+###############################################################################
+## Monit configuration for syncd container
+## process list:
+## syncd
+###############################################################################
+check process syncd matching "/usr/bin/syncd"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/platform/marvell-arm64/docker-syncd-mrvl/supervisord.conf b/platform/marvell-arm64/docker-syncd-mrvl/supervisord.conf
index 1af5d70a1d0c..b11e045fac7e 100644
--- a/platform/marvell-arm64/docker-syncd-mrvl/supervisord.conf
+++ b/platform/marvell-arm64/docker-syncd-mrvl/supervisord.conf
@@ -3,6 +3,12 @@ logfile_maxbytes=1MB
logfile_backups=2
nodaemon=true
+[eventlistener:supervisor-proc-exit-listener]
+command=/usr/bin/supervisor-proc-exit-listener --container-name syncd
+events=PROCESS_STATE_EXITED
+autostart=true
+autorestart=unexpected
+
[program:start.sh]
command=/usr/bin/start.sh
priority=1
diff --git a/platform/marvell-armhf/docker-syncd-mrvl-rpc.mk b/platform/marvell-armhf/docker-syncd-mrvl-rpc.mk
index 0e1b65f2fd5d..c3ce6c10119c 100644
--- a/platform/marvell-armhf/docker-syncd-mrvl-rpc.mk
+++ b/platform/marvell-armhf/docker-syncd-mrvl-rpc.mk
@@ -2,7 +2,7 @@
DOCKER_SYNCD_MRVL_RPC = docker-syncd-mrvl-rpc.gz
$(DOCKER_SYNCD_MRVL_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-mrvl-rpc
-$(DOCKER_SYNCD_MRVL_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT)
+$(DOCKER_SYNCD_MRVL_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(PTF)
$(DOCKER_SYNCD_MRVL_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)
ifeq ($(INSTALL_DEBUG_TOOLS), y)
$(DOCKER_SYNCD_MRVL_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \
diff --git a/platform/marvell-armhf/docker-syncd-mrvl.mk b/platform/marvell-armhf/docker-syncd-mrvl.mk
index e00769a59700..841e3b4b165f 100644
--- a/platform/marvell-armhf/docker-syncd-mrvl.mk
+++ b/platform/marvell-armhf/docker-syncd-mrvl.mk
@@ -11,3 +11,4 @@ $(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \
$(LIBSAIREDIS_DBG)
$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /host/warmboot:/var/warmboot
+$(DOCKER_SYNCD_BASE)_BASE_IMAGE_FILES += monit_syncd:/etc/monit/conf.d
diff --git a/platform/marvell-armhf/docker-syncd-mrvl/base_image_files/monit_syncd b/platform/marvell-armhf/docker-syncd-mrvl/base_image_files/monit_syncd
new file mode 100644
index 000000000000..3079618990ed
--- /dev/null
+++ b/platform/marvell-armhf/docker-syncd-mrvl/base_image_files/monit_syncd
@@ -0,0 +1,7 @@
+###############################################################################
+## Monit configuration for syncd container
+## process list:
+## syncd
+###############################################################################
+check process syncd matching "/usr/bin/syncd"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/platform/marvell-armhf/docker-syncd-mrvl/supervisord.conf b/platform/marvell-armhf/docker-syncd-mrvl/supervisord.conf
index 1af5d70a1d0c..b11e045fac7e 100644
--- a/platform/marvell-armhf/docker-syncd-mrvl/supervisord.conf
+++ b/platform/marvell-armhf/docker-syncd-mrvl/supervisord.conf
@@ -3,6 +3,12 @@ logfile_maxbytes=1MB
logfile_backups=2
nodaemon=true
+[eventlistener:supervisor-proc-exit-listener]
+command=/usr/bin/supervisor-proc-exit-listener --container-name syncd
+events=PROCESS_STATE_EXITED
+autostart=true
+autorestart=unexpected
+
[program:start.sh]
command=/usr/bin/start.sh
priority=1
diff --git a/platform/marvell-armhf/linux-kernel-armhf.mk b/platform/marvell-armhf/linux-kernel-armhf.mk
index 32e8ea3c604a..4d52beac49d9 100644
--- a/platform/marvell-armhf/linux-kernel-armhf.mk
+++ b/platform/marvell-armhf/linux-kernel-armhf.mk
@@ -1,7 +1,7 @@
# linux kernel package for marvell armhf
# Add platform specific DTB
-LINUX_KERNEL_DTB = linux-image-4.9.168-armhf.deb
+LINUX_KERNEL_DTB = linux-image-4.9.189-armhf.deb
$(LINUX_KERNEL_DTB)_URL = https://github.com/Marvell-switching/sonic-marvell-binaries/raw/master/armhf/kernel/$(LINUX_KERNEL_DTB)
SONIC_ONLINE_DEBS += $(LINUX_KERNEL_DTB)
SONIC_STRETCH_DEBS += $(LINUX_KERNEL_DTB)
diff --git a/platform/marvell/docker-syncd-mrvl-rpc.mk b/platform/marvell/docker-syncd-mrvl-rpc.mk
index 5b1968bde39c..92d616fa2cab 100644
--- a/platform/marvell/docker-syncd-mrvl-rpc.mk
+++ b/platform/marvell/docker-syncd-mrvl-rpc.mk
@@ -2,7 +2,7 @@
DOCKER_SYNCD_MRVL_RPC = docker-syncd-mrvl-rpc.gz
$(DOCKER_SYNCD_MRVL_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-mrvl-rpc
-$(DOCKER_SYNCD_MRVL_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT)
+$(DOCKER_SYNCD_MRVL_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(PTF)
$(DOCKER_SYNCD_MRVL_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)
ifeq ($(INSTALL_DEBUG_TOOLS), y)
$(DOCKER_SYNCD_MRVL_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \
diff --git a/platform/marvell/docker-syncd-mrvl.mk b/platform/marvell/docker-syncd-mrvl.mk
index 5257bf5e68e7..97b7eab19895 100644
--- a/platform/marvell/docker-syncd-mrvl.mk
+++ b/platform/marvell/docker-syncd-mrvl.mk
@@ -12,3 +12,4 @@ $(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \
$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /host/warmboot:/var/warmboot
$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd
+$(DOCKER_SYNCD_BASE)_BASE_IMAGE_FILES += monit_syncd:/etc/monit/conf.d
diff --git a/platform/marvell/docker-syncd-mrvl/base_image_files/monit_syncd b/platform/marvell/docker-syncd-mrvl/base_image_files/monit_syncd
new file mode 100644
index 000000000000..3079618990ed
--- /dev/null
+++ b/platform/marvell/docker-syncd-mrvl/base_image_files/monit_syncd
@@ -0,0 +1,7 @@
+###############################################################################
+## Monit configuration for syncd container
+## process list:
+## syncd
+###############################################################################
+check process syncd matching "/usr/bin/syncd"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/platform/marvell/docker-syncd-mrvl/supervisord.conf b/platform/marvell/docker-syncd-mrvl/supervisord.conf
index aea4d45b9afd..43de2426f981 100644
--- a/platform/marvell/docker-syncd-mrvl/supervisord.conf
+++ b/platform/marvell/docker-syncd-mrvl/supervisord.conf
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name syncd
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
diff --git a/platform/mellanox/docker-syncd-mlnx-rpc.mk b/platform/mellanox/docker-syncd-mlnx-rpc.mk
index 608c1bb3ad20..ef2aec3333ac 100644
--- a/platform/mellanox/docker-syncd-mlnx-rpc.mk
+++ b/platform/mellanox/docker-syncd-mlnx-rpc.mk
@@ -2,7 +2,7 @@
DOCKER_SYNCD_MLNX_RPC = docker-syncd-mlnx-rpc.gz
$(DOCKER_SYNCD_MLNX_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-mlnx-rpc
-$(DOCKER_SYNCD_MLNX_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT)
+$(DOCKER_SYNCD_MLNX_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(PTF)
$(DOCKER_SYNCD_MLNX_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)
ifeq ($(INSTALL_DEBUG_TOOLS), y)
$(DOCKER_SYNCD_MLNX_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \
@@ -20,7 +20,7 @@ SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_MLNX_RPC)
endif
$(DOCKER_SYNCD_MLNX_RPC)_CONTAINER_NAME = syncd
-$(DOCKER_SYNCD_MLNX_RPC)_RUN_OPT += --net=host --privileged -t
+$(DOCKER_SYNCD_MLNX_RPC)_RUN_OPT += --privileged -t
$(DOCKER_SYNCD_MLNX_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf
$(DOCKER_SYNCD_MLNX_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro
$(DOCKER_SYNCD_MLNX_RPC)_RUN_OPT += -v /host/warmboot:/var/warmboot
diff --git a/platform/mellanox/docker-syncd-mlnx-rpc/Dockerfile.j2 b/platform/mellanox/docker-syncd-mlnx-rpc/Dockerfile.j2
index d9b86e782531..3f6225c96bd3 100644
--- a/platform/mellanox/docker-syncd-mlnx-rpc/Dockerfile.j2
+++ b/platform/mellanox/docker-syncd-mlnx-rpc/Dockerfile.j2
@@ -4,6 +4,8 @@ FROM docker-syncd-mlnx
## Make apt-get non-interactive
ENV DEBIAN_FRONTEND=noninteractive
+RUN mkdir -p /var/run/sx_sdk
+
RUN apt-get purge -y syncd
{% if docker_syncd_mlnx_rpc_debs.strip() -%}
diff --git a/platform/mellanox/docker-syncd-mlnx.mk b/platform/mellanox/docker-syncd-mlnx.mk
index db582e517bff..9bdc5a8ad8ec 100644
--- a/platform/mellanox/docker-syncd-mlnx.mk
+++ b/platform/mellanox/docker-syncd-mlnx.mk
@@ -15,4 +15,4 @@ $(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(MLNX_SDK_DBG_DEBS) $(MLNX_SAI_DBGSYM)
endif
$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /host/warmboot:/var/warmboot
-
+$(DOCKER_SYNCD_BASE)_BASE_IMAGE_FILES += monit_syncd:/etc/monit/conf.d
diff --git a/platform/mellanox/docker-syncd-mlnx/Dockerfile.j2 b/platform/mellanox/docker-syncd-mlnx/Dockerfile.j2
index 4d22335ec783..6953933735fa 100755
--- a/platform/mellanox/docker-syncd-mlnx/Dockerfile.j2
+++ b/platform/mellanox/docker-syncd-mlnx/Dockerfile.j2
@@ -4,6 +4,8 @@ FROM docker-config-engine-stretch
ARG docker_container_name
RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf
+RUN mkdir -p /var/run/sx_sdk
+
## Make apt-get non-interactive
ENV DEBIAN_FRONTEND=noninteractive
diff --git a/platform/mellanox/docker-syncd-mlnx/base_image_files/monit_syncd b/platform/mellanox/docker-syncd-mlnx/base_image_files/monit_syncd
new file mode 100644
index 000000000000..3079618990ed
--- /dev/null
+++ b/platform/mellanox/docker-syncd-mlnx/base_image_files/monit_syncd
@@ -0,0 +1,7 @@
+###############################################################################
+## Monit configuration for syncd container
+## process list:
+## syncd
+###############################################################################
+check process syncd matching "/usr/bin/syncd"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/platform/mellanox/docker-syncd-mlnx/supervisord.conf b/platform/mellanox/docker-syncd-mlnx/supervisord.conf
index c823ab5680ef..0c6285d46ae0 100644
--- a/platform/mellanox/docker-syncd-mlnx/supervisord.conf
+++ b/platform/mellanox/docker-syncd-mlnx/supervisord.conf
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name syncd
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
diff --git a/platform/mellanox/fw.mk b/platform/mellanox/fw.mk
index eb1a58cfda9d..faa3b3f239b6 100644
--- a/platform/mellanox/fw.mk
+++ b/platform/mellanox/fw.mk
@@ -1,4 +1,4 @@
-# mellanox firmware
+# mellanox asic firmware
MLNX_FW_BASE_PATH = $(MLNX_SDK_BASE_PATH)
@@ -11,24 +11,36 @@ else
FW_FROM_URL = n
endif
-MLNX_SPC_FW_VERSION = 13.2000.2696
+MLNX_SPC_FW_VERSION = 13.2007.0872
MLNX_SPC_FW_FILE = fw-SPC-rel-$(subst .,_,$(MLNX_SPC_FW_VERSION))-EVB.mfa
$(MLNX_SPC_FW_FILE)_PATH = $(MLNX_FW_BASE_PATH)
$(MLNX_SPC_FW_FILE)_URL = $(MLNX_FW_BASE_URL)/$(MLNX_SPC_FW_FILE)
-MLNX_SPC2_FW_VERSION = 29.2000.2696
+MLNX_SPC2_FW_VERSION = 29.2007.0872
MLNX_SPC2_FW_FILE = fw-SPC2-rel-$(subst .,_,$(MLNX_SPC2_FW_VERSION))-EVB.mfa
$(MLNX_SPC2_FW_FILE)_PATH = $(MLNX_FW_BASE_PATH)
$(MLNX_SPC2_FW_FILE)_URL = $(MLNX_FW_BASE_URL)/$(MLNX_SPC2_FW_FILE)
+MLNX_SPC3_FW_VERSION = 30.2007.0872
+MLNX_SPC3_FW_FILE = fw-SPC3-rel-$(subst .,_,$(MLNX_SPC3_FW_VERSION))-EVB.mfa
+$(MLNX_SPC3_FW_FILE)_PATH = $(MLNX_FW_BASE_PATH)
+$(MLNX_SPC3_FW_FILE)_URL = $(MLNX_FW_BASE_URL)/$(MLNX_SPC3_FW_FILE)
+
+MLNX_FW_FILES = $(MLNX_SPC_FW_FILE) $(MLNX_SPC2_FW_FILE) $(MLNX_SPC3_FW_FILE)
+
ifeq ($(FW_FROM_URL),n)
-SONIC_COPY_FILES += $(MLNX_SPC_FW_FILE) $(MLNX_SPC2_FW_FILE)
+SONIC_COPY_FILES += $(MLNX_FW_FILES)
else
-SONIC_ONLINE_FILES += $(MLNX_SPC_FW_FILE) $(MLNX_SPC2_FW_FILE)
+SONIC_ONLINE_FILES += $(MLNX_FW_FILES)
endif
+MLNX_FILES += $(MLNX_FW_FILES)
+
export MLNX_SPC_FW_VERSION
export MLNX_SPC_FW_FILE
export MLNX_SPC2_FW_VERSION
export MLNX_SPC2_FW_FILE
+
+export MLNX_SPC3_FW_VERSION
+export MLNX_SPC3_FW_FILE
diff --git a/platform/mellanox/hw-management.mk b/platform/mellanox/hw-management.mk
index ff1ea207572d..692a816a0f4f 100644
--- a/platform/mellanox/hw-management.mk
+++ b/platform/mellanox/hw-management.mk
@@ -1,6 +1,6 @@
# Mellanox HW Management
-MLNX_HW_MANAGEMENT_VERSION = 7.0000.2308
+MLNX_HW_MANAGEMENT_VERSION = 7.0000.3012
export MLNX_HW_MANAGEMENT_VERSION
diff --git a/platform/mellanox/hw-management/0001-Make-hw-mgmt-SimX-compatiable.patch b/platform/mellanox/hw-management/0001-Make-hw-mgmt-SimX-compatiable.patch
index 31a85434fb49..a72c94473e88 100644
--- a/platform/mellanox/hw-management/0001-Make-hw-mgmt-SimX-compatiable.patch
+++ b/platform/mellanox/hw-management/0001-Make-hw-mgmt-SimX-compatiable.patch
@@ -1,7 +1,7 @@
-From 051938b7c49cc18aaddd699939353f591554d635 Mon Sep 17 00:00:00 2001
+From ebb17bd1f6996f73cb67313846a63c789e74c4f4 Mon Sep 17 00:00:00 2001
From: Mykola Faryma
-Date: Wed, 3 Apr 2019 14:09:26 +0000
-Subject: [PATCH] Make hw-mgmt SimX compatiable.
+Date: Fri, 21 Feb 2020 12:28:54 +0200
+Subject: [PATCH 1/1] Make hw-mgmt SimX compatiable
Signed-off-by: Mykola Faryma
---
@@ -9,45 +9,45 @@ Signed-off-by: Mykola Faryma
1 file changed, 29 insertions(+)
diff --git a/usr/usr/bin/hw-management.sh b/usr/usr/bin/hw-management.sh
-index fdb3013..68da9bc 100755
+index 1b5b18a..3dfd4b1 100755
--- a/usr/usr/bin/hw-management.sh
+++ b/usr/usr/bin/hw-management.sh
-@@ -646,6 +646,35 @@ do_chip_down()
+@@ -943,6 +943,35 @@ do_chip_down()
/usr/bin/hw-management-thermal-events.sh change hotplug_asic down %S %p
}
+handle_simx()
+{
-+ local -r onie_platform="$(cat /host/machine.conf | grep onie_platform | cut -d= -f2)"
++ local -r onie_platform="$(cat /host/machine.conf | grep onie_platform | cut -d= -f2)"
+
-+ local -r syseeprom_cache_path="/var/cache/sonic/decode-syseeprom/syseeprom_cache"
-+ local -r syseeprom_hex_path="/usr/share/sonic/device/${onie_platform}/syseeprom.hex"
-+ local -r syseeprom_vpd_path="/var/run/hw-management/eeprom/vpd_info"
++ local -r syseeprom_cache_path="/var/cache/sonic/decode-syseeprom/syseeprom_cache"
++ local -r syseeprom_hex_path="/usr/share/sonic/device/${onie_platform}/syseeprom.hex"
++ local -r syseeprom_vpd_path="/var/run/hw-management/eeprom/vpd_info"
+
-+ case $ACTION in
-+ start)
-+ /bin/bash -c "/bin/rm -f ${syseeprom_cache_path}"
-+ /bin/bash -c "/bin/mkdir -p ${eeprom_path}"
-+ /bin/bash -c "/usr/bin/xxd -r -p ${syseeprom_hex_path} ${syseeprom_vpd_path}"
-+ ;;
-+ stop)
-+ /bin/bash -c "/bin/rm -fr ${hw_management_path}"
-+ ;;
-+ *)
-+ echo "Usage: `basename $0` {start|stop}"
-+ exit 1
-+ ;;
-+ esac
++ case $ACTION in
++ start)
++ /bin/bash -c "/bin/rm -f ${syseeprom_cache_path}"
++ /bin/bash -c "/bin/mkdir -p ${eeprom_path}"
++ /bin/bash -c "/usr/bin/xxd -r -p ${syseeprom_hex_path} ${syseeprom_vpd_path}"
++ ;;
++ stop)
++ /bin/bash -c "/bin/rm -fr ${hw_management_path}"
++ ;;
++ *)
++ echo "Usage: `basename $0` {start|stop}"
++ exit 1
++ ;;
++ esac
+}
+
-+if [[ "$(cat /sys/devices/virtual/dmi/id/chassis_vendor)" = "QEMU" ]]; then
-+ handle_simx
-+ exit 0
++if [[ "$(cat /sys/devices/virtual/dmi/id/sys_vendor)" = "QEMU" ]]; then
++ handle_simx
++ exit 0
+fi
+
case $ACTION in
start)
- do_start
+ if [ -d /var/run/hw-management ]; then
--
1.9.1
diff --git a/platform/mellanox/hw-management/hw-mgmt b/platform/mellanox/hw-management/hw-mgmt
index 28d83cdb3565..2f659142ab3b 160000
--- a/platform/mellanox/hw-management/hw-mgmt
+++ b/platform/mellanox/hw-management/hw-mgmt
@@ -1 +1 @@
-Subproject commit 28d83cdb3565d3b0352cc718fe82a14cacd1d4a5
+Subproject commit 2f659142ab3b4deb58989a2ca38b0b1671600509
diff --git a/platform/mellanox/issu-version.mk b/platform/mellanox/issu-version.mk
index c7ae4296ab7a..db368ffd8c10 100644
--- a/platform/mellanox/issu-version.mk
+++ b/platform/mellanox/issu-version.mk
@@ -5,5 +5,6 @@ $(ISSU_VERSION_FILE)_SRC_PATH = $(PLATFORM_PATH)/issu-version
$(ISSU_VERSION_FILE)_DEPENDS += $(APPLIBS)
SONIC_MAKE_FILES += $(ISSU_VERSION_FILE)
-export ISSU_VERSION_FILE
+MLNX_FILES += $(ISSU_VERSION_FILE)
+export ISSU_VERSION_FILE
diff --git a/platform/mellanox/mft.mk b/platform/mellanox/mft.mk
index ae2c92e0ac18..229ba86b4a7b 100644
--- a/platform/mellanox/mft.mk
+++ b/platform/mellanox/mft.mk
@@ -1,7 +1,7 @@
# Mellanox SAI
-MFT_VERSION = 4.12.0
-MFT_REVISION = 104
+MFT_VERSION = 4.14.0
+MFT_REVISION = 500
export MFT_VERSION MFT_REVISION
diff --git a/platform/mellanox/mlnx-ffb.mk b/platform/mellanox/mlnx-ffb.mk
index dabb995a3658..82d50b7ae3e3 100755
--- a/platform/mellanox/mlnx-ffb.mk
+++ b/platform/mellanox/mlnx-ffb.mk
@@ -4,4 +4,6 @@ MLNX_FFB_SCRIPT = mlnx-ffb.sh
$(MLNX_FFB_SCRIPT)_PATH = platform/mellanox/
SONIC_COPY_FILES += $(MLNX_FFB_SCRIPT)
+MLNX_FILES += $(MLNX_FFB_SCRIPT)
+
export MLNX_FFB_SCRIPT
diff --git a/platform/mellanox/mlnx-fw-upgrade.j2 b/platform/mellanox/mlnx-fw-upgrade.j2
index 3857244a1504..d0f69c35e0bc 100755
--- a/platform/mellanox/mlnx-fw-upgrade.j2
+++ b/platform/mellanox/mlnx-fw-upgrade.j2
@@ -25,15 +25,18 @@ declare -r QUERY_FILE="/tmp/mlxfwmanager-query.log"
declare -r SPC1_ASIC="spc1"
declare -r SPC2_ASIC="spc2"
+declare -r SPC3_ASIC="spc3"
declare -r UNKN_ASIC="unknown"
declare -rA FW_FILE_MAP=( \
[$SPC1_ASIC]="/etc/mlnx/fw-SPC.mfa" \
[$SPC2_ASIC]="/etc/mlnx/fw-SPC2.mfa" \
+ [$SPC3_ASIC]="/etc/mlnx/fw-SPC3.mfa" \
)
declare -rA FW_REQUIRED_MAP=( \
[$SPC1_ASIC]="{{ MLNX_SPC_FW_VERSION }}" \
[$SPC2_ASIC]="{{ MLNX_SPC2_FW_VERSION }}" \
+ [$SPC3_ASIC]="{{ MLNX_SPC3_FW_VERSION }}" \
)
IMAGE_UPGRADE="${NO_PARAM}"
@@ -135,6 +138,7 @@ function GetAsicType() {
local -r SPC1_PRODUCT_ID="cb84"
local -r SPC2_PRODUCT_ID="cf6c"
+ local -r SPC3_PRODUCT_ID="cf70"
if lspci -n | grep "${VENDOR_ID}:${SPC1_PRODUCT_ID}" &>/dev/null; then
echo "${SPC1_ASIC}"
@@ -142,6 +146,9 @@ function GetAsicType() {
elif lspci -n | grep "${VENDOR_ID}:${SPC2_PRODUCT_ID}" &>/dev/null; then
echo "${SPC2_ASIC}"
exit "${EXIT_SUCCESS}"
+ elif lspci -n | grep "${VENDOR_ID}:${SPC3_PRODUCT_ID}" &>/dev/null; then
+ echo "${SPC3_ASIC}"
+ exit "${EXIT_SUCCESS}"
fi
echo "${UNKN_ASIC}"
diff --git a/platform/mellanox/mlnx-onie-fw-update.mk b/platform/mellanox/mlnx-onie-fw-update.mk
new file mode 100644
index 000000000000..825c12c30ba4
--- /dev/null
+++ b/platform/mellanox/mlnx-onie-fw-update.mk
@@ -0,0 +1,9 @@
+# onie update tool
+
+MLNX_ONIE_FW_UPDATE = mlnx-onie-fw-update.sh
+$(MLNX_ONIE_FW_UPDATE)_PATH = platform/mellanox/
+SONIC_COPY_FILES += $(MLNX_ONIE_FW_UPDATE)
+
+MLNX_FILES += $(MLNX_ONIE_FW_UPDATE)
+
+export MLNX_ONIE_FW_UPDATE
diff --git a/platform/mellanox/mlnx-onie-fw-update.sh b/platform/mellanox/mlnx-onie-fw-update.sh
new file mode 100755
index 000000000000..314f4ed70268
--- /dev/null
+++ b/platform/mellanox/mlnx-onie-fw-update.sh
@@ -0,0 +1,120 @@
+#!/bin/sh
+
+# Copyright (C) 2019 Mellanox Technologies Ltd.
+# Copyright (C) 2019 Michael Shych
+#
+# SPDX-License-Identifier: GPL-2.0
+
+this_script=${ONIE_FWPKG_PROGRAM_NAME:-$(basename $(realpath $0))}
+
+onie_mount=/mnt/onie-boot
+os_boot=/host
+onie_partition=
+
+export ONIE_FWPKG_PROGRAM_NAME=$(basename $(realpath $0))
+
+usage()
+{
+cat < before update."
+ clean_onie_access
+ exit 1
+ fi
+ ;;
+ purge | show | show-results | show-log | show-pending | help)
+ ;;
+ *)
+ echo "Unknown command: $cmd"
+ exit 1
+ ;;
+esac
+
+enable_onie_access
+$onie_mount/onie/tools/bin/onie-fwpkg "$@"
+rc=$?
+if [ $cmd = "help" ]; then
+ usage
+fi
+clean_onie_access
+
+exit $rc
diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py
index 44ef8981281f..5edb82bfe517 100644
--- a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py
+++ b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py
@@ -11,6 +11,7 @@
try:
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform_base.component_base import ComponentBase
+ from sonic_device_util import get_machine_info
from sonic_daemon_base.daemon_base import Logger
from os import listdir
from os.path import isfile, join
@@ -43,7 +44,7 @@
# magic code defnition for port number, qsfp port position of each hwsku
# port_position_tuple = (PORT_START, QSFP_PORT_START, PORT_END, PORT_IN_BLOCK, EEPROM_OFFSET)
-hwsku_dict_port = {'ACS-MSN2010': 3, 'ACS-MSN2100': 1, 'ACS-MSN2410': 2, 'ACS-MSN2700': 0, 'Mellanox-SN2700': 0, 'Mellanox-SN2700-D48C8': 0, 'LS-SN2700':0, 'ACS-MSN2740': 0, 'ACS-MSN3700': 0, 'ACS-MSN3700C': 0, 'ACS-MSN3800': 4}
+hwsku_dict_port = {'ACS-MSN2010': 3, 'ACS-MSN2100': 1, 'ACS-MSN2410': 2, 'ACS-MSN2700': 0, 'Mellanox-SN2700': 0, 'Mellanox-SN2700-D48C8': 0, 'LS-SN2700':0, 'ACS-MSN2740': 0, 'ACS-MSN3700': 0, 'ACS-MSN3700C': 0, 'ACS-MSN3800': 4, 'Mellanox-SN3800-D112C8': 4, 'ACS-MSN4700': 0}
port_position_tuple_list = [(0, 0, 31, 32, 1), (0, 0, 15, 16, 1), (0, 48, 55, 56, 1), (0, 18, 21, 22, 1), (0, 0, 63, 64, 1)]
class Chassis(ChassisBase):
@@ -54,6 +55,11 @@ def __init__(self):
# Initialize SKU name
self.sku_name = self._get_sku_name()
+ mi = get_machine_info()
+ if mi is not None:
+ self.name = mi['onie_platform']
+ else:
+ self.name = self.sku_name
# move the initialization of each components to their dedicated initializer
# which will be called from platform
@@ -133,7 +139,17 @@ def initialize_components(self):
# Initialize component list
from sonic_platform.component import ComponentBIOS, ComponentCPLD
self._component_list.append(ComponentBIOS())
- self._component_list.append(ComponentCPLD())
+ self._component_list.extend(ComponentCPLD.get_component_list())
+
+
+ def get_name(self):
+ """
+ Retrieves the name of the device
+
+ Returns:
+ string: The name of the device
+ """
+ return self.name
##############################################
@@ -417,25 +433,12 @@ def get_change_event(self, timeout=0):
timeout = MAX_SELECT_DELAY
while True:
status = self.sfp_event.check_sfp_status(port_dict, timeout)
- if not port_dict == {}:
+ if bool(port_dict):
break
else:
status = self.sfp_event.check_sfp_status(port_dict, timeout)
if status:
- # get_change_event has the meaning of retrieving all the notifications through a single call.
- # Typically this is implemented via a select framework which requires the underlay file-reading
- # interface able to retrieve all notifications without blocking once the fd has been selected.
- # However, sdk doesn't provide any interface satisfied the requirement. as a result,
- # check_sfp_status returns only one notification may indicate more notifications in its queue.
- # In this sense, we have to iterate in a loop to get all the notifications in case that
- # the first call returns at least one.
- i = 0
- while i < self.MAX_SELECT_EVENT_RETURNED:
- status = self.sfp_event.check_sfp_status(port_dict, 0)
- if not status:
- break
- i = i + 1
return True, {'sfp':port_dict}
else:
return True, {'sfp':{}}
diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/component.py b/platform/mellanox/mlnx-platform-api/sonic_platform/component.py
index fd593f7bbe45..13e3953a03ad 100644
--- a/platform/mellanox/mlnx-platform-api/sonic_platform/component.py
+++ b/platform/mellanox/mlnx-platform-api/sonic_platform/component.py
@@ -5,25 +5,28 @@
#
# implementation of new platform api
#############################################################################
-
+from __future__ import print_function
try:
from sonic_platform_base.component_base import ComponentBase
+ from sonic_device_util import get_machine_info
from glob import glob
import subprocess
import io
+ import os
import re
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
-#components definitions
-COMPONENT_BIOS = "BIOS"
-COMPONENT_CPLD = "CPLD"
-
-BIOS_QUERY_VERSION_COMMAND = 'dmidecode -t 11'
-CPLD_VERSION_FILE_PATTERN = '/var/run/hw-management/system/cpld[0-9]_version'
-CPLD_VERSION_MAX_LENGTH = 4
+ZERO = '0'
+NEWLINE = '\n'
class Component(ComponentBase):
+ def __init__(self):
+ self.name = None
+ self.description = None
+ self.image_ext_name = None
+
+
def get_name(self):
"""
Retrieves the name of the component
@@ -34,25 +37,42 @@ def get_name(self):
return self.name
- def _read_generic_file(self, filename, len):
+ def get_description(self):
+ """
+ Retrieves the description of the component
+
+ Returns:
+ A string containing the description of the component
+ """
+ return self.description
+
+
+ @staticmethod
+ def _read_generic_file(filename, len, ignore_errors=False):
"""
Read a generic file, returns the contents of the file
"""
- result = ''
+ result = None
+
try:
with io.open(filename, 'r') as fileobj:
result = fileobj.read(len)
- return result
except IOError as e:
- raise RuntimeError("Failed to read file {} due to {}".format(filename, repr(e)))
+ if not ignore_errors:
+ raise RuntimeError("Failed to read file {} due to {}".format(filename, repr(e)))
+
+ return result
- def _get_command_result(self, cmdline):
+ @staticmethod
+ def _get_command_result(cmdline):
try:
proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT)
stdout = proc.communicate()[0]
- proc.wait()
+ rc = proc.wait()
result = stdout.rstrip('\n')
+ if rc != 0:
+ raise RuntimeError("Failed to execute command {}, return code {}, message {}".format(cmdline, rc, stdout))
except OSError as e:
raise RuntimeError("Failed to execute command {} due to {}".format(cmdline, repr(e)))
@@ -60,22 +80,50 @@ def _get_command_result(self, cmdline):
return result
-class ComponentBIOS(Component):
- BIOS_VERSION_PARSE_PATTERN = 'OEM[\s]*Strings\n[\s]*String[\s]*1:[\s]*([0-9a-zA-Z_\.]*)'
+ def _check_file_validity(self, image_path):
+ # check whether the image file exists
+ if not os.path.isfile(image_path):
+ print("ERROR: File {} doesn't exist or is not a file".format(image_path))
+ return False
+ if self.image_ext_name is not None:
+ name_list = os.path.splitext(image_path)
+ if name_list[1] != self.image_ext_name:
+ print("ERROR: Extend name of file {} is wrong. Image for {} should have extend name {}".format(image_path, self.name, self.image_ext_name))
+ return False
- def __init__(self):
- self.name = COMPONENT_BIOS
+ return True
- def get_description(self):
- """
- Retrieves the description of the component
- Returns:
- A string containing the description of the component
- """
- return "BIOS - Basic Input/Output System"
+class ComponentBIOS(Component):
+ COMPONENT_NAME = 'BIOS'
+ COMPONENT_DESCRIPTION = 'BIOS - Basic Input/Output System'
+ COMPONENT_FIRMWARE_EXTENSION = '.rom'
+
+ # To update BIOS requires the ONIE with version 5.2.0016 or upper
+ ONIE_VERSION_PARSE_PATTERN = '[0-9]{4}\.[0-9]{2}-([0-9]+)\.([0-9]+)\.([0-9]+)'
+ ONIE_VERSION_MAJOR_OFFSET = 1
+ ONIE_VERSION_MINOR_OFFSET = 2
+ ONIE_VERSION_RELEASE_OFFSET = 3
+ ONIE_REQUIRED_MAJOR = '5'
+ ONIE_REQUIRED_MINOR = '2'
+ ONIE_REQUIRED_RELEASE = '0016'
+
+ BIOS_VERSION_PARSE_PATTERN = 'OEM[\s]*Strings\n[\s]*String[\s]*1:[\s]*([0-9a-zA-Z_\.]*)'
+ BIOS_PENDING_UPDATE_PATTERN = '([0-9A-Za-z_]*.rom)[\s]*\|[\s]*bios_update'
+
+ ONIE_FW_UPDATE_CMD_ADD = '/usr/bin/mlnx-onie-fw-update.sh add {}'
+ ONIE_FW_UPDATE_CMD_REMOVE = '/usr/bin/mlnx-onie-fw-update.sh remove {}'
+ ONIE_FW_UPDATE_CMD_UPDATE = '/usr/bin/mlnx-onie-fw-update.sh update'
+ ONIE_FW_UPDATE_CMD_SHOW = '/usr/bin/mlnx-onie-fw-update.sh show-pending'
+
+ BIOS_QUERY_VERSION_COMMAND = 'dmidecode -t 11'
+
+ def __init__(self):
+ self.name = self.COMPONENT_NAME
+ self.description = self.COMPONENT_DESCRIPTION
+ self.image_ext_name = self.COMPONENT_FIRMWARE_EXTENSION
def get_firmware_version(self):
@@ -99,30 +147,110 @@ def get_firmware_version(self):
By using regular expression 'OEM[\s]*Strings\n[\s]*String[\s]*1:[\s]*([0-9a-zA-Z_\.]*)'
we can extrace the version string which is marked with * in the above context
"""
- bios_ver_str = self._get_command_result(BIOS_QUERY_VERSION_COMMAND)
try:
+ bios_ver_str = self._get_command_result(self.BIOS_QUERY_VERSION_COMMAND)
m = re.search(self.BIOS_VERSION_PARSE_PATTERN, bios_ver_str)
result = m.group(1)
- except AttributeError as e:
- raise RuntimeError("Failed to parse BIOS version by {} from {} due to {}".format(
- self.BIOS_VERSION_PARSE_PATTERN, bios_ver_str, repr(e)))
+ except (AttributeError, RuntimeError) as e:
+ raise RuntimeError("Failed to parse BIOS version due to {}".format(repr(e)))
return result
-class ComponentCPLD(Component):
- def __init__(self):
- self.name = COMPONENT_CPLD
+ def _check_onie_version(self):
+ # check ONIE version. To update ONIE requires version 5.2.0016 or later.
+ try:
+ machine_info = get_machine_info()
+ onie_version_string = machine_info['onie_version']
+ m = re.search(self.ONIE_VERSION_PARSE_PATTERN, onie_version_string)
+ onie_major = m.group(self.ONIE_VERSION_MAJOR_OFFSET)
+ onie_minor = m.group(self.ONIE_VERSION_MINOR_OFFSET)
+ onie_release = m.group(self.ONIE_VERSION_RELEASE_OFFSET)
+ except AttributeError as e:
+ print("ERROR: Failed to parse ONIE version by {} from {} due to {}".format(
+ self.ONIE_VERSION_PARSE_PATTERN, machine_conf, repr(e)))
+ return False
+ if onie_major < self.ONIE_REQUIRED_MAJOR or onie_minor < self.ONIE_REQUIRED_MINOR or onie_release < self.ONIE_REQUIRED_RELEASE:
+ print("ERROR: ONIE {}.{}.{} or later is required".format(self.ONIE_REQUIRED_MAJOR, self.ONIE_REQUIRED_MINOR, self.ONIE_REQUIRED_RELEASE))
+ return False
- def get_description(self):
+ return True
+
+
+ def install_firmware(self, image_path):
"""
- Retrieves the description of the component
+ Installs firmware to the component
+
+ Args:
+ image_path: A string, path to firmware image
Returns:
- A string containing the description of the component
+ A boolean, True if install was successful, False if not
"""
- return "CPLD - includes all CPLDs in the switch"
+ # check ONIE version requirement
+ if not self._check_onie_version():
+ return False
+
+ # check whether the file exists
+ if not self._check_file_validity(image_path):
+ return False
+
+ # do the real work
+ try:
+ # check whether there has already been some images pending
+ # if yes, remove them
+ result = self._get_command_result(self.ONIE_FW_UPDATE_CMD_SHOW)
+ pending_list = result.split("\n")
+ for pending in pending_list:
+ m = re.match(self.BIOS_PENDING_UPDATE_PATTERN, pending)
+ if m is not None:
+ pending_image = m.group(1)
+ self._get_command_result(self.ONIE_FW_UPDATE_CMD_REMOVE.format(pending_image))
+ print("WARNING: Image {} which is already pending to upgrade has been removed".format(pending_image))
+
+ result = subprocess.check_call(self.ONIE_FW_UPDATE_CMD_ADD.format(image_path).split())
+ if result:
+ return False
+ result = subprocess.check_call(self.ONIE_FW_UPDATE_CMD_UPDATE.split())
+ if result:
+ return False
+ except Exception as e:
+ print("ERROR: Installing BIOS failed due to {}".format(repr(e)))
+ return False
+
+ print("INFO: Reboot is required to finish BIOS installation")
+ return True
+
+
+
+class ComponentCPLD(Component):
+ COMPONENT_NAME = 'CPLD{}'
+ COMPONENT_DESCRIPTION = 'CPLD - Complex Programmable Logic Device'
+ COMPONENT_FIRMWARE_EXTENSION = '.vme'
+
+ CPLD_NUMBER_FILE = '/var/run/hw-management/config/cpld_num'
+ CPLD_PART_NUMBER_FILE = '/var/run/hw-management/system/cpld{}_pn'
+ CPLD_VERSION_FILE = '/var/run/hw-management/system/cpld{}_version'
+ CPLD_VERSION_MINOR_FILE = '/var/run/hw-management/system/cpld{}_version_minor'
+
+ CPLD_NUMBER_MAX_LENGTH = 1
+ CPLD_PART_NUMBER_MAX_LENGTH = 6
+ CPLD_VERSION_MAX_LENGTH = 2
+ CPLD_VERSION_MINOR_MAX_LENGTH = 2
+
+ CPLD_PART_NUMBER_DEFAULT = ZERO
+ CPLD_VERSION_MINOR_DEFAULT = ZERO
+
+ CPLD_UPDATE_COMMAND = 'cpldupdate --dev {} --print-progress {}'
+
+ MST_DEVICE_PATTERN = '/dev/mst/mt[0-9]*_pci_cr0'
+
+ def __init__(self, idx):
+ self.idx = idx
+ self.name = self.COMPONENT_NAME.format(self.idx)
+ self.description = self.COMPONENT_DESCRIPTION
+ self.image_ext_name = self.COMPONENT_FIRMWARE_EXTENSION
def get_firmware_version(self):
@@ -132,17 +260,92 @@ def get_firmware_version(self):
Returns:
A string containing the firmware version of the component
"""
- cpld_version_file_list = glob(CPLD_VERSION_FILE_PATTERN)
- cpld_version = ''
- if cpld_version_file_list is not None and cpld_version_file_list:
- cpld_version_file_list.sort()
- for version_file in cpld_version_file_list:
- version = self._read_generic_file(version_file, CPLD_VERSION_MAX_LENGTH)
- if not cpld_version == '':
- cpld_version += '.'
- cpld_version += version.rstrip('\n')
- else:
- raise RuntimeError("Failed to get CPLD version files by matching {}".format(CPLD_VERSION_FILE_PATTERN))
-
- return cpld_version
+ part_number_file = self.CPLD_PART_NUMBER_FILE.format(self.idx)
+ version_file = self.CPLD_VERSION_FILE.format(self.idx)
+ version_minor_file = self.CPLD_VERSION_MINOR_FILE.format(self.idx)
+
+ part_number = self._read_generic_file(part_number_file, self.CPLD_PART_NUMBER_MAX_LENGTH, True)
+ version = self._read_generic_file(version_file, self.CPLD_VERSION_MAX_LENGTH)
+ version_minor = self._read_generic_file(version_minor_file, self.CPLD_VERSION_MINOR_MAX_LENGTH, True)
+
+ if part_number is None:
+ part_number = self.CPLD_PART_NUMBER_DEFAULT
+
+ if version_minor is None:
+ version_minor = self.CPLD_VERSION_MINOR_DEFAULT
+
+ part_number = part_number.rstrip(NEWLINE).zfill(self.CPLD_PART_NUMBER_MAX_LENGTH)
+ version = version.rstrip(NEWLINE).zfill(self.CPLD_VERSION_MAX_LENGTH)
+ version_minor = version_minor.rstrip(NEWLINE).zfill(self.CPLD_VERSION_MINOR_MAX_LENGTH)
+
+ return "CPLD{}_REV{}{}".format(part_number, version, version_minor)
+
+
+ def _get_mst_device(self):
+ mst_dev_list = glob(self.MST_DEVICE_PATTERN)
+ if mst_dev_list is None or len(mst_dev_list) != 1:
+ return None
+ return mst_dev_list
+
+
+ def install_firmware(self, image_path):
+ """
+ Installs firmware to the component
+
+ Args:
+ image_path: A string, path to firmware image
+
+ Returns:
+ A boolean, True if install was successful, False if not
+
+ Details:
+ The command "cpldupdate" is provided to install CPLD. There are two ways to do it:
+ 1. To burn CPLD via gpio, which is faster but only supported on new systems, like SN3700, ...
+ 2. To install CPLD via firmware, which is slower but supported on older systems.
+ This also requires the mst device designated.
+ "cpldupdate --dev " has the logic of testing whether to update via gpio is supported,
+ and if so then go this way, otherwise tries updating software via fw. So we take advantage of it to update the CPLD.
+ By doing so we don't have to mind whether to update via gpio supported, which belongs to hardware details.
+
+ So the procedure should be:
+ 1. Test whether the file exists
+ 2. Fetch the mst device name
+ 3. Update CPLD via executing "cpldupdate --dev "
+ 4. Check the result
+ """
+ # check whether the image file exists
+ if not self._check_file_validity(image_path):
+ return False
+
+ mst_dev_list = self._get_mst_device()
+ if mst_dev_list is None:
+ print("ERROR: Failed to get mst device which is required for CPLD updating or multiple device files matched")
+ return False
+
+ cmdline = self.CPLD_UPDATE_COMMAND.format(mst_dev_list[0], image_path)
+ success_flag = False
+
+ try:
+ subprocess.check_call(cmdline, stderr=subprocess.STDOUT, shell=True)
+ success_flag = True
+ except subprocess.CalledProcessError as e:
+ print("ERROR: Failed to upgrade CPLD: rc={}".format(e.returncode))
+
+ if success_flag:
+ print("INFO: Refresh or power cycle is required to finish CPLD installation")
+
+ return success_flag
+
+
+ @classmethod
+ def get_component_list(cls):
+ component_list = [ ]
+
+ cpld_number = cls._read_generic_file(cls.CPLD_NUMBER_FILE, cls.CPLD_NUMBER_MAX_LENGTH)
+ cpld_number = cpld_number.rstrip(NEWLINE)
+
+ for cpld_idx in xrange(1, int(cpld_number) + 1):
+ component_list.append(cls(cpld_idx))
+
+ return component_list
diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py b/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py
index 0789f67e4f09..045e5a842993 100644
--- a/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py
+++ b/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py
@@ -32,7 +32,7 @@
# in most SKUs the file psuX_curr, psuX_volt and psuX_power contain current, voltage and power data respectively.
# but there are exceptions which will be handled by the following dictionary
-hwsku_dict_psu = {'ACS-MSN3700': 1, 'ACS-MSN3700C': 1, 'ACS-MSN3800': 1}
+hwsku_dict_psu = {'ACS-MSN3700': 1, 'ACS-MSN3700C': 1, 'ACS-MSN3800': 1, 'Mellanox-SN3800-D112C8': 1, 'ACS-MSN4700': 1}
psu_profile_list = [
# default filename convention
{
@@ -40,7 +40,7 @@
PSU_VOLTAGE : "power/psu{}_volt",
PSU_POWER : "power/psu{}_power"
},
- # for 3700, 3700c, 3800
+ # for 3700, 3700c, 3800, 4700
{
PSU_CURRENT : "power/psu{}_curr",
PSU_VOLTAGE : "power/psu{}_volt_out2",
diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp_event.py b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp_event.py
index e92884fc3f33..0ed75c26c63a 100644
--- a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp_event.py
+++ b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp_event.py
@@ -11,15 +11,69 @@
from python_sdk_api.sx_api import *
from sonic_daemon_base.daemon_base import Logger
-SDK_SFP_STATE_IN = 0x1
+# SFP status from PMAOS register
+# 0x1 plug in
+# 0x2 plug out
+# 0x3 plug in with error
+# 0x4 disabled, at this status SFP eeprom is not accessible,
+# and presence status also will be not present,
+# so treate it as plug out.
+SDK_SFP_STATE_IN = 0x1
SDK_SFP_STATE_OUT = 0x2
+SDK_SFP_STATE_ERR = 0x3
+SDK_SFP_STATE_DIS = 0x4
+
+# SFP status that will be handled by XCVRD
STATUS_PLUGIN = '1'
STATUS_PLUGOUT = '0'
-STATUS_UNKNOWN = '2'
+STATUS_ERR_I2C_STUCK = '2'
+STATUS_ERR_BAD_EEPROM = '3'
+STATUS_ERR_UNSUPPORTED_CABLE = '4'
+STATUS_ERR_HIGH_TEMP = '5'
+STATUS_ERR_BAD_CABLE = '6'
+
+# SFP status used in this file only, will not expose to XCVRD
+# STATUS_ERROR will be mapped to different status according to the error code
+STATUS_UNKNOWN = '-1'
+STATUS_ERROR = '-2'
+
+# SFP error code, only valid when SFP at SDK_SFP_STATE_ERR status
+# Only 0x2, 0x3, 0x5, 0x6 and 0x7 will block the eeprom access,
+# so will only report above errors to XCVRD and other errors will be
+# printed to syslog.
+
+'''
+0x0: "Power_Budget_Exceeded",
+0x1: "Long_Range_for_non_MLNX_cable_or_module",
+0x2: "Bus_stuck",
+0x3: "bad_or_unsupported_EEPROM",
+0x4: "Enforce_part_number_list",
+0x5: "unsupported_cable",
+0x6: "High_Temperature",
+0x7: "bad_cable",
+0x8: "PMD_type_is_not_enabled",
+0x9: "[internal]Laster_TEC_failure",
+0xa: "[internal]High_current",
+0xb: "[internal]High_voltage",
+0xd: "[internal]High_power",
+0xe: "[internal]Module_state_machine_fault",
+0xc: "pcie_system_power_slot_Exceeded"
+'''
+
+# SFP errors that will block eeprom accessing
+sdk_sfp_err_type_dict = {
+ 0x2: STATUS_ERR_I2C_STUCK,
+ 0x3: STATUS_ERR_BAD_EEPROM,
+ 0x5: STATUS_ERR_UNSUPPORTED_CABLE,
+ 0x6: STATUS_ERR_HIGH_TEMP,
+ 0x7: STATUS_ERR_BAD_CABLE
+}
sfp_value_status_dict = {
- SDK_SFP_STATE_IN: STATUS_PLUGIN,
- SDK_SFP_STATE_OUT: STATUS_PLUGOUT,
+ SDK_SFP_STATE_IN: STATUS_PLUGIN,
+ SDK_SFP_STATE_OUT: STATUS_PLUGOUT,
+ SDK_SFP_STATE_ERR: STATUS_ERROR,
+ SDK_SFP_STATE_DIS: STATUS_PLUGOUT,
}
# system level event/error
@@ -174,7 +228,7 @@ def check_sfp_status(self, port_change, timeout):
for fd in read:
if fd == self.rx_fd_p.fd:
- success, port_list, module_state = self.on_pmpe(self.rx_fd_p)
+ success, port_list, module_state, error_type = self.on_pmpe(self.rx_fd_p)
if not success:
logger.log_error("failed to read from {}".format(fd))
break
@@ -192,15 +246,23 @@ def check_sfp_status(self, port_change, timeout):
found += 1
continue
+ # If get SFP status error(0x3) from SDK, then need to read the error_type to get the detailed error
+ if sfp_state == STATUS_ERROR:
+ if error_type in sdk_sfp_err_type_dict.keys():
+ # In SFP at error status case, need to overwrite the sfp_state with the exact error code
+ sfp_state = sdk_sfp_err_type_dict[error_type]
+ else:
+ # For errors don't block the eeprom accessing, we don't report it to XCVRD
+ logger.log_info("SFP error on port but not blocking eeprom read, error_type {}".format(error_type))
+ found +=1
+ continue
+
for port in port_list:
logger.log_info("SFP on port {} state {}".format(port, sfp_state))
port_change[port] = sfp_state
found += 1
- if found == 0:
- return False
- else:
- return True
+ return found != 0
def on_pmpe(self, fd_p):
''' on port module plug event handler '''
@@ -228,7 +290,17 @@ def on_pmpe(self, fd_p):
port_list_size = pmpe_t.list_size
logical_port_list = pmpe_t.log_port_list
module_state = pmpe_t.module_state
-
+ error_type = pmpe_t.error_type
+ module_id = pmpe_t.module_id
+
+ if module_state == SDK_SFP_STATE_ERR:
+ logger.log_error("Receive PMPE error event on module {}: status {} error type {}".format(module_id, module_state, error_type))
+ elif module_state == SDK_SFP_STATE_DIS:
+ logger.log_info("Receive PMPE disable event on module {}: status {}".format(module_id, module_state))
+ elif module_state == SDK_SFP_STATE_IN or module_state == SDK_SFP_STATE_OUT:
+ logger.log_info("Receive PMPE plug in/out event on module {}: status {}".format(module_id, module_state))
+ else:
+ logger.log_error("Receive PMPE unknown event on module {}: status {}".format(module_id, module_state))
for i in xrange(port_list_size):
logical_port = sx_port_log_id_t_arr_getitem(logical_port_list, i)
rc = sx_api_port_device_get(self.handle, 1 , 0, port_attributes_list, port_cnt_p)
@@ -247,4 +319,4 @@ def on_pmpe(self, fd_p):
delete_sx_port_attributes_t_arr(port_attributes_list)
delete_uint32_t_p(port_cnt_p)
- return status, label_port_list, module_state,
+ return status, label_port_list, module_state, error_type
diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py
index 6862b3fb258b..903b55404bb3 100644
--- a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py
+++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py
@@ -106,7 +106,7 @@
THERMAL_API_GET_HIGH_THRESHOLD
]
-hwsku_dict_thermal = {'ACS-MSN2700': 0, 'LS-SN2700':0, 'ACS-MSN2740': 3, 'ACS-MSN2100': 1, 'ACS-MSN2410': 2, 'ACS-MSN2010': 4, 'ACS-MSN3700': 5, 'ACS-MSN3700C': 6, 'Mellanox-SN2700': 0, 'Mellanox-SN2700-D48C8': 0, 'ACS-MSN3800': 7}
+hwsku_dict_thermal = {'ACS-MSN2700': 0, 'LS-SN2700':0, 'ACS-MSN2740': 3, 'ACS-MSN2100': 1, 'ACS-MSN2410': 2, 'ACS-MSN2010': 4, 'ACS-MSN3700': 5, 'ACS-MSN3700C': 6, 'Mellanox-SN2700': 0, 'Mellanox-SN2700-D48C8': 0, 'ACS-MSN3800': 7, 'Mellanox-SN3800-D112C8': 7, 'ACS-MSN4700': 8}
thermal_profile_list = [
# 2700
{
@@ -231,6 +231,22 @@
]
)
},
+ # 4700
+ {
+ THERMAL_DEV_CATEGORY_CPU_CORE:(0, 4),
+ THERMAL_DEV_CATEGORY_MODULE:(1, 32),
+ THERMAL_DEV_CATEGORY_PSU:(1, 2),
+ THERMAL_DEV_CATEGORY_CPU_PACK:(0,1),
+ THERMAL_DEV_CATEGORY_GEARBOX:(0,0),
+ THERMAL_DEV_CATEGORY_AMBIENT:(0,
+ [
+ THERMAL_DEV_ASIC_AMBIENT,
+ THERMAL_DEV_COMEX_AMBIENT,
+ THERMAL_DEV_PORT_AMBIENT,
+ THERMAL_DEV_FAN_AMBIENT
+ ]
+ )
+ }
]
def initialize_thermals(sku, thermal_list, psu_list):
diff --git a/platform/mellanox/mlnx-sai.mk b/platform/mellanox/mlnx-sai.mk
index 39942111f26a..275445bd80e0 100644
--- a/platform/mellanox/mlnx-sai.mk
+++ b/platform/mellanox/mlnx-sai.mk
@@ -1,6 +1,6 @@
# Mellanox SAI
-MLNX_SAI_VERSION = SAIRel1.15.2-master
+MLNX_SAI_VERSION = SAIRel1.16.2-master
export MLNX_SAI_VERSION
diff --git a/platform/mellanox/mlnx-sai/SAI-Implementation b/platform/mellanox/mlnx-sai/SAI-Implementation
index d878245e364c..5eb3e143e3da 160000
--- a/platform/mellanox/mlnx-sai/SAI-Implementation
+++ b/platform/mellanox/mlnx-sai/SAI-Implementation
@@ -1 +1 @@
-Subproject commit d878245e364ce8d5edd08bbd7120c44c92362235
+Subproject commit 5eb3e143e3da934b30fd9b66126a6ab626f1b15e
diff --git a/platform/mellanox/mlnx-ssd-fw-update.mk b/platform/mellanox/mlnx-ssd-fw-update.mk
new file mode 100644
index 000000000000..f932e57d2521
--- /dev/null
+++ b/platform/mellanox/mlnx-ssd-fw-update.mk
@@ -0,0 +1,9 @@
+# ssd update tool
+
+MLNX_SSD_FW_UPDATE = mlnx-ssd-fw-update.sh
+$(MLNX_SSD_FW_UPDATE)_PATH = platform/mellanox/
+SONIC_COPY_FILES += $(MLNX_SSD_FW_UPDATE)
+
+MLNX_FILES += $(MLNX_SSD_FW_UPDATE)
+
+export MLNX_SSD_FW_UPDATE
diff --git a/platform/mellanox/mlnx-ssd-fw-update.sh b/platform/mellanox/mlnx-ssd-fw-update.sh
new file mode 100755
index 000000000000..5163c8e7f8f7
--- /dev/null
+++ b/platform/mellanox/mlnx-ssd-fw-update.sh
@@ -0,0 +1,727 @@
+#!/bin/bash
+########################################################################
+# Copyright (c) 2020 Mellanox Technologies. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the names of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# Alternatively, this software may be distributed under the terms of the
+# GNU General Public License ("GPL") version 2 as published by the Free
+# Software Foundation.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+#==============================================================================#
+#= Global variable #
+#=
+#=====
+VERSION="1.3"
+#=====
+SWITCH_SSD_DEV="/dev/sda"
+UTIL_TITLE="This is MLNX SSD firmware update utility to read and write SSD FW. Version ${VERSION}"
+DEPENDECIES=("smartctl" "sha256sum" "tar" "/bin/bash" "gpg" "sed" "realpath" "dirname")
+TRUE="0"
+FALSE="1"
+ERR_MSG="ERR_MSG"
+INI_PREFIX="ini_section_"
+PUBLIC_CERT_NAME="trusted.gpg"
+CHECKSUM_NAME="checksum"
+SCRIPT_MODE="RELESE" # RELESE -or- DEBUG
+DEBUG_MSG="DEBUG" # remove all instance after script is ready.
+#=====
+PKG_EXTRACTED=$FALSE
+LOGGER_UTIL=$FALSE
+SSD_FW_VER=""
+SSD_DEVICE_MODEL=""
+SSD_SERIAL=""
+SSD_SIZE=""
+SECTIONS=()
+#=====
+ARG_IMAGE_FLAG=$FALSE
+ARG_IMAGE_VAL=""
+ARG_QUERY_FLAG=$FALSE
+ARG_YES_FLAG=$FALSE
+ARG_POWER_CYCLE_FLAG=$FALSE
+ARG_HELP_FLAG=$FALSE
+ARG_VERSION_FLAG=$FALSE
+ARG_PACKAGE_INFO_FLAG=$FALSE
+ARG_UPDATE_FLAG=$FALSE
+
+
+
+#==============================================================================#
+#= usage function. #
+#=
+function init_script() {
+# check if logger utility supported
+ if [ -x "$(command -v logger)" ]; then
+ LOGGER_UTIL=$TRUE
+ else
+ LOGGER_UTIL=$FALSE
+ fi
+}
+
+#==============================================================================#
+#= usage function. #
+#=
+function usage() {
+ echo
+ echo -e "$UTIL_TITLE"
+ echo
+ echo -e "Usage:"
+ echo -e "\tmlnx_ssd_fw_update.sh [OPTION]"
+ echo -e "Commands:"
+ echo -e "\t-i, --image\t\t Path to SSD FW package"
+ echo -e "\t-q, --query\t\t Print SSD information (SSD model, serial number, version and size)"
+ echo -e "\t\t\t\t Combined with image, comparison is made if update is required"
+ echo -e "\t-p, --package-info\t Get package info"
+ echo -e "\t-u, --update\t\t Upgrade firmware"
+ echo -e "\t-y --yes\t\t Assume \"yes\" to all questions"
+ echo -e "\t-V, --version\t\t Print utility version"
+ echo -e "\t-h, --help\t\t Show this usage"
+ echo -e "\t --power-cycle\t Execute power cycle at completion, even if not required"
+ echo
+ echo -e "Example:"
+ echo -e "\tmlnx_ssd_fw_update.sh -q"
+ echo -e "\tmlnx_ssd_fw_update.sh -q -i mlnx_ssd_fw_package.pkg"
+ echo -e "\tmlnx_ssd_fw_update.sh -p -i mlnx_ssd_fw_package.pkg"
+ echo -e "\tmlnx_ssd_fw_update.sh -u -i mlnx_ssd_fw_package.pkg"
+ echo
+}
+
+#==============================================================================#
+#= Log function. #
+#=
+function LOG_MSG() {
+ if [ $# -gt 0 ]; then
+ LOG_STR=$1
+ if [[ $# -eq 1 ]]; then
+ [[ "$LOGGER_UTIL" == "$TRUE" && "$LOG_STR" != "" ]] && logger -t mlnx_ssd_fw_update.sh -p user.notice $(echo "$LOG_STR" | sed 's/\\t//g')
+ echo -e "$LOG_STR"
+ elif [[ $# -eq 2 && "$2" == "$ERR_MSG" ]]; then
+ [[ "$LOGGER_UTIL" == "$TRUE" && "$LOG_STR" != "" ]] && logger -t mlnx_ssd_fw_update.sh -p user.err $(echo "$LOG_STR" | sed 's/\\t//g')
+ echo -e "$LOG_STR"
+ elif [[ $# -eq 2 && "$2" == "$SCRIPT_MODE" ]]; then
+ echo -e "DBG: $LOG_STR"
+ fi
+ fi
+}
+
+#==============================================================================#
+#= Log function. #
+#=
+function LOG_MSG_AND_EXIT() {
+ LOG_MSG "$@" "$ERR_MSG"
+ erase_extract_package "$extraction_path"
+ LOG_MSG "Exiting..."
+ exit 1
+}
+
+#==============================================================================#
+#= This function check if given argument is valid and return boolean result. #
+#=
+function check_usage() {
+ local argument_count=$#
+
+ LOG_MSG "Number of argument:$argument_count" ${DEBUG_MSG}
+
+ if [ $# -eq 0 ]; then
+ LOG_MSG "Error: false usage given."
+ usage
+ exit 1
+ fi
+
+ while [[ $# -gt 0 ]]
+ do
+ key="$1"
+
+ case $key in
+ -i|--image)
+ ARG_IMAGE_FLAG=$TRUE
+ ARG_IMAGE_VAL="$2"
+ shift # past argument
+ shift # past value
+ ;;
+ -q|--query)
+ ARG_QUERY_FLAG=$TRUE
+ shift # past argument
+ ;;
+ -y|--yes)
+ ARG_YES_FLAG=$TRUE
+ shift # past argument
+ ;;
+ -h|--help)
+ ARG_HELP_FLAG=$TRUE
+ shift # past argument
+ ;;
+ -V|--version)
+ ARG_VERSION_FLAG=$TRUE
+ shift # past argument
+ ;;
+ -u|--update)
+ ARG_UPDATE_FLAG=$TRUE
+ shift # past argument
+ ;;
+ -p|--package-info)
+ ARG_PACKAGE_INFO_FLAG=$TRUE
+ shift # past argument
+ ;;
+ --power-cycle)
+ ARG_POWER_CYCLE_FLAG=$TRUE
+ shift # past argument
+ ;;
+ *)
+ LOG_MSG "Error: false usage given."
+ usage
+ exit 1
+ ;;
+ esac
+ done
+
+ if [[ ("$ARG_IMAGE_FLAG" == "$TRUE" && ( $argument_count -lt 3 )) ||
+ ("$ARG_IMAGE_FLAG" == "$TRUE" && ( $argument_count -gt 5 )) ||
+ ("$ARG_PACKAGE_INFO_FLAG" == "$TRUE" && ( $argument_count -ne 3 )) ||
+ ("$ARG_QUERY_FLAG" == "$TRUE" && ( $argument_count -lt 1 )) ||
+ ("$ARG_QUERY_FLAG" == "$TRUE" && ( $argument_count -gt 3 )) ||
+ ("$ARG_HELP_FLAG" == "$TRUE" && ( $argument_count -gt 1 )) ||
+ ("$ARG_VERSION_FLAG" == "$TRUE" && ( $argument_count -gt 1 )) ||
+ ("$ARG_IMAGE_FLAG" == "$TRUE" && "$ARG_IMAGE_VAL" == "") ||
+ ("$ARG_UPDATE_FLAG" == "$TRUE" && "$ARG_IMAGE_FLAG" == "$FALSE") ||
+ ("$ARG_PACKAGE_INFO_FLAG" == "$TRUE" && "$ARG_IMAGE_FLAG" == "$FALSE") ||
+ ("$ARG_POWER_CYCLE_FLAG" == "$TRUE" && "$ARG_UPDATE_FLAG" == "$FALSE") ||
+ ("$ARG_UPDATE_FLAG" == "$TRUE" && "$ARG_PACKAGE_INFO_FLAG" == "$TRUE") ]]; then
+
+ LOG_MSG "Error: false usage given."
+ usage
+ exit 1
+ fi
+
+### Debug message remove when script is done.
+ LOG_MSG "ARG_IMAGE_FLAG = ${ARG_IMAGE_FLAG}" ${DEBUG_MSG}
+ LOG_MSG "ARG_IMAGE_VAL = ${ARG_IMAGE_VAL}" ${DEBUG_MSG}
+ LOG_MSG "ARG_QUERY_FLAG = ${ARG_QUERY_FLAG}" ${DEBUG_MSG}
+ LOG_MSG "ARG_YES_FLAG = ${ARG_YES_FLAG}" ${DEBUG_MSG}
+ LOG_MSG "ARG_HELP_FLAG = ${ARG_HELP_FLAG}" ${DEBUG_MSG}
+ LOG_MSG "ARG_VERSION_FLAG = ${ARG_VERSION_FLAG}" ${DEBUG_MSG}
+ LOG_MSG "ARG_PACKAGE_INFO_FLAG = ${ARG_PACKAGE_INFO_FLAG}" ${DEBUG_MSG}
+ LOG_MSG "ARG_POWER_CYCLE_FLAG = ${ARG_POWER_CYCLE_FLAG}" ${DEBUG_MSG}
+
+}
+
+#==============================================================================#
+# This function return SSD fw version using hdparm utility #
+#
+function get_ssd_fw_version() {
+ [ $1 ] || { LOG_MSG_AND_EXIT "Wrong usage - ${FUNCNAME[0]}()"; }
+
+ local device_fw_version
+ device_fw_version=$(smartctl -i $SWITCH_SSD_DEV | grep -Po "Firmware Version: +\K[^,]+")
+ LOG_MSG "device_fw_version: $device_fw_version" ${DEBUG_MSG}
+ eval $1='$device_fw_version'
+}
+
+#==============================================================================#
+# This function return SSD device model using hdparm utility #
+#
+function get_ssd_device_model() {
+ [ $1 ] || { LOG_MSG_AND_EXIT "Wrong usage - ${FUNCNAME[0]}()"; }
+
+ local device_model_name
+ device_model_name=$(smartctl -i $SWITCH_SSD_DEV | grep -Po "Device Model: +\K[^,]+")
+ LOG_MSG "device_model_name: $device_model_name" ${DEBUG_MSG}
+ eval $1='$device_model_name'
+}
+
+#==============================================================================#
+# This function return SSD size using hdparm utility #
+#
+function get_ssd_size() {
+ [ $1 ] || { LOG_MSG_AND_EXIT "Wrong usage - ${FUNCNAME[0]}()"; }
+
+ local device_size
+ device_size=$(smartctl -i $SWITCH_SSD_DEV | grep -Po "User Capacity:.+bytes \[\K[^ ]+")
+ LOG_MSG "device_size: $device_size" ${DEBUG_MSG}
+ eval $1='$device_size'
+}
+
+#==============================================================================#
+# This function return SSD serial using hdparm utility #
+#
+function get_ssd_serial() {
+ [ $1 ] || { LOG_MSG_AND_EXIT "Wrong usage - ${FUNCNAME[0]}()"; }
+
+ local device_serial
+ device_serial=$(smartctl -i $SWITCH_SSD_DEV | grep -Po "Serial Number: +\K[^,]+")
+ LOG_MSG "device_serial: $device_serial" ${DEBUG_MSG}
+ eval $1='$device_serial'
+}
+
+#==============================================================================#
+#= This function check if given argument is valid and return boolean result. #
+#=
+function get_ssd_info() {
+ LOG_MSG "func: ${FUNCNAME[0]}()" ${DEBUG_MSG}
+ get_ssd_fw_version SSD_FW_VER
+ get_ssd_device_model SSD_DEVICE_MODEL
+ get_ssd_serial SSD_SERIAL
+ get_ssd_size SSD_SIZE
+}
+
+#==============================================================================#
+#= This function check if given argument is valid and return boolean result. #
+#=
+function check_tool_dependencies() {
+ LOG_MSG "func: ${FUNCNAME[0]}()" ${DEBUG_MSG}
+ for i in "${!DEPENDECIES[@]}"
+ do
+ if [ ! -x "$(command -v ${DEPENDECIES[$i]})" ]; then
+ LOG_MSG_AND_EXIT "Error: This tool require the following utils to be installed ${DEPENDECIES[$i]}"
+ fi
+ done
+}
+
+#==============================================================================#
+#= This function parse package ini file and declare it attributes #
+#=
+function ini_parser {
+ LOG_MSG "func: ${FUNCNAME[0]}()" ${DEBUG_MSG}
+
+ local filename="$1"
+ LOG_MSG "filename:$filename" ${DEBUG_MSG}
+
+ shopt -p extglob &> /dev/null
+ CHANGE_EXTGLOB=$?
+ if [ $CHANGE_EXTGLOB = 1 ]
+ then
+ shopt -s extglob
+ fi
+ ini="$(<$filename)" # read the file
+ ini=${ini//$'\r'/} # remove linefeed i.e dos2unix
+ ini="${ini//[/\\[}"
+ ini="${ini//]/\\]}"
+ IFS=$'\n' && ini=( ${ini} ) # convert to line-array
+ ini=( ${ini[*]//\)/\\\)} ) # append / before any parenthesis
+ ini=( ${ini[*]//\(/\\\(} ) # append / before any parenthesis
+ ini=( ${ini[*]/#*([[:space:]]);*/} )
+ ini=( ${ini[*]/#*([[:space:]])\#*/} )
+ ini=( ${ini[*]/#+([[:space:]])/} ) # remove init whitespace
+ ini=( ${ini[*]/%+([[:space:]])/} ) # remove ending whitespace
+ ini=( ${ini[*]/*([[:space:]])=*([[:space:]])/=} ) # remove whitespace around =
+ ini=( ${ini[*]/#\\[/\}$'\n'"$INI_PREFIX"} ) # set section prefix
+ ini=( ${ini[*]/%\\]/ \(} ) # convert text2function (1)
+ ini=( ${ini[*]/=/=\( } ) # convert item to array
+ ini=( ${ini[*]/%/ \)} ) # close array parenthesis
+ ini=( ${ini[*]/%\\ \)/ \\} ) # the multiline trick
+ ini=( ${ini[*]/%\( \)/\(\) \{} ) # convert text2function (2)
+ ini=( ${ini[*]/%\} \)/\}} ) # remove extra parenthesis
+ ini=( ${ini[*]/%\{/\{$'\n''ini_unset ${FUNCNAME/#'$INI_PREFIX'}'$'\n'} ) # clean previous definition of section
+ ini[0]="" # remove first element
+ ini[${#ini[*]} + 1]='}' # add the last brace
+ eval "$(echo "${ini[*]}")" # eval the result
+ [ $? -ne 0 ] && LOG_MSG_AND_EXIT "Error: failed to parse package content."
+ SECTIONS="$(echo ${ini[*]} | grep -Po "$INI_PREFIX+\K[\w]+")"
+ if [ $CHANGE_EXTGLOB = 1 ]
+ then
+ shopt -u extglob
+ fi
+}
+
+#==============================================================================#
+#= This function unset parse ini section and variables #
+#=
+function ini_unset {
+ LOG_MSG "func: ${FUNCNAME[0]}()" ${DEBUG_MSG}
+ SECTION=$1
+ OLDIFS="$IFS"
+ IFS=' '$'\n'
+ if [ -z "$SECTION" ]
+ then
+ fun="$(declare -F)"
+ else
+ fun="$(declare -F $INI_PREFIX$SECTION)"
+ if [ -z "$fun" ]
+ then
+ echo "section $SECTION not found" 1>&2
+ return
+ fi
+ fi
+ fun="${fun//declare -f/}"
+ for f in $fun; do
+ [ "${f#$INI_PREFIX}" == "${f}" ] && continue
+ item="$(declare -f ${f})"
+ item="${item##*\{}" # remove function definition
+ item="${item##*FUNCNAME*$INI_PREFIX\};}" # remove clear section
+ item="${item/\}}" # remove function close
+ item="${item%)*}" # remove everything after parenthesis
+ item="${item});" # add close parenthesis
+ vars=""
+ while [ "$item" != "" ]
+ do
+ newvar="${item%%=*}" # get item name
+ vars="$vars $newvar" # add name to collection
+ item="${item#*;}" # remove readed line
+ done
+ for var in $vars; do
+ unset $var
+ done
+ done
+ IFS="$OLDIFS"
+}
+
+#==============================================================================#
+#= This function check package signing and returns back true or false #
+#=
+function check_package_signing() {
+ LOG_MSG "func: ${FUNCNAME[0]}()" ${DEBUG_MSG}
+
+ [ $1 ] || { LOG_MSG_AND_EXIT "Wrong usage - ${FUNCNAME[0]}()"; }
+
+ local package_path=$1
+ local checksum_unsigned_file="$package_path/$CHECKSUM_NAME"
+ local checksum_signed_file="$package_path/$CHECKSUM_NAME.sig"
+ local public_cert_file="$package_path/$PUBLIC_CERT_NAME"
+
+### Check if unsigned checksum file exists
+ [ ! -f "$checksum_unsigned_file" ] && LOG_MSG_AND_EXIT "Error: fail to find unsigned checksum file to verify package signing."
+
+### Check if signed checksum file exists
+ [ ! -f "$checksum_signed_file" ] && LOG_MSG_AND_EXIT "Error: fail to find sign checksum file to verify package signing."
+
+### Check if public key exists
+ [ ! -f "$public_cert_file" ] && LOG_MSG_AND_EXIT "Error: fail to find public certificate to verify package signing."
+
+
+ LOG_MSG "public_cert_file: ${public_cert_file}" ${DEBUG_MSG}
+ LOG_MSG "checksum_signed_file: ${checksum_signed_file}" ${DEBUG_MSG}
+ LOG_MSG "checksum_unsigned_file: ${checksum_unsigned_file}" ${DEBUG_MSG}
+
+ gpg --keyring "$public_cert_file" --verify "$checksum_signed_file" "$checksum_unsigned_file" > /dev/null 2>&1
+ [ $? -ne 0 ] && LOG_MSG_AND_EXIT "Error: fault package signing."
+
+ LOG_MSG "cd into: ${package_path}" ${DEBUG_MSG}
+ cd $package_path > /dev/null 2>&1
+ sha256sum -c $CHECKSUM_NAME > /dev/null 2>&1
+ [ $? -ne 0 ] && LOG_MSG_AND_EXIT "Error: fault package SHA signing, file has been compromised"
+ LOG_MSG "backing back:" ${DEBUG_MSG}
+ cd - > /dev/null 2>&1
+ LOG_MSG "exiting:" ${DEBUG_MSG}
+
+}
+
+#==============================================================================#
+#= This function prints supported SSD from package ini #
+#=
+function string_supported_model() {
+
+ local section=$1
+
+ if [[ ! -z "${Vendor[*]}" ]] && [[ ! -z "${SSD_FW_Model[*]}" ]] && [[ ! -z "${SSD_FW_Version[*]}" ]] \
+ && [[ ! -z "${SSD_Size[*]}" ]] && [[ ! -z ${Shutdown_Policy[*]} ]]; then
+ printf 'o %-10s | %-30s | %-12s | %-6sGB | %-7s |\n' \
+ "$( IFS=$'\n'; echo "${Vendor[@]}" )" "$( IFS=$'\n'; echo "${SSD_FW_Model[@]}" )" \
+ "${SSD_FW_Version[@]}" "${SSD_Size[@]}" "${Shutdown_Policy[@],,}"
+ fi
+
+}
+
+#==============================================================================#
+#= This function extract SSD FW package into /tmp #
+#=
+function extract_package() {
+ LOG_MSG "func: ${FUNCNAME[0]}()" ${DEBUG_MSG}
+
+ local filename=$1
+ LOG_MSG "filename:$filename" ${DEBUG_MSG}
+### Check if file exists
+ [ ! -f $filename ] && LOG_MSG_AND_EXIT "Error: given file ($filename) not found."
+### Check if tmp available
+ [ ! -d "/tmp" ] && LOG_MSG_AND_EXIT "Error: directory /tmp DOES NOT exists."
+
+ local base_filename="${filename##*/}"
+ local folder_name="/tmp/""${base_filename%%.*}"
+
+### Check if full path available
+ if [ -d $folder_name ]; then
+ LOG_MSG "Path:$folder_name already exists, removing folder." ${DEBUG_MSG}
+ rm -rf ${folder_name}
+ [ $? -ne 0 ] && LOG_MSG_AND_EXIT "Error: folder:$folder_name is already in use and can't be overwrite, please remove it and retry."
+ fi
+
+ mkdir ${folder_name} && tar xf ${filename} -C ${folder_name} --strip-components 1 --warning=no-timestamp > /dev/null 2>&1
+ #tar -xf $filename --directory /tmp/ --warning=no-timestamp > /dev/null 2>&1
+### Check if untar succeed.
+ [ $? -ne 0 ] && LOG_MSG_AND_EXIT "Error: fail to extract given package ($filename)."
+
+### return the path file extraction is
+ # local base_filename="${filename##*/}"
+ # local folder_name="/tmp/""${base_filename%%.*}"
+ eval $2="$folder_name"
+
+ PKG_EXTRACTED=$TRUE
+
+ check_package_signing $folder_name
+
+ LOG_MSG "successfully untar file." ${DEBUG_MSG}
+}
+
+#==============================================================================#
+#= This function extract SSD FW package into /tmp #
+#=
+function erase_extract_package() {
+ LOG_MSG "func: ${FUNCNAME[0]}()" ${DEBUG_MSG}
+
+ [[ "$PKG_EXTRACTED" == "$FALSE" ]] && return
+
+ local folder_name=$1
+
+ LOG_MSG "folder_name: $folder_name" ${DEBUG_MSG}
+
+### Check if folder exists
+ if [ ! -d "$folder_name" ]; then
+ LOG_MSG "Error: directory $folder_name DOES NOT exists." "$ERR_MSG"
+ LOG_MSG "Exiting..."
+ exit 1
+ fi
+ rm -rf $folder_name
+### Check if untar succeed.
+ if [ $? -ne 0 ]; then
+ LOG_MSG "Error: fail to delete $folder_name folder." "$ERR_MSG"
+ LOG_MSG "Exiting..."
+ exit 1
+ fi
+
+ PKG_EXTRACTED=$FALSE
+ LOG_MSG "successfully removed folder:$folder_name" ${DEBUG_MSG}
+}
+
+
+#==============================================================================#
+#= This function returns back ini section array.
+#=
+function call_ini_section() {
+ LOG_MSG "func: ${FUNCNAME[0]}()" ${DEBUG_MSG}
+
+ local ini_section=$1
+ LOG_MSG "ini_section:$ini_section" ${DEBUG_MSG}
+
+ [[ -z "$ini_section" ]] && LOG_MSG_AND_EXIT "Error: given INI section is null."
+ [[ -z "$(declare -F "$INI_PREFIX$ini_section")" ]] && LOG_MSG_AND_EXIT "Error: $ini_section section is missing in INI file."
+
+ eval "$(echo "$INI_PREFIX$ini_section")" # call given section function.
+}
+
+#==============================================================================#
+#= This function prints ssd info
+#=
+function print_ssd_info() {
+ LOG_MSG "func: ${FUNCNAME[0]}()" ${DEBUG_MSG}
+
+ local argument_count=$#
+
+ if [ $argument_count -eq 2 ]; then
+ local newer_fw_version=$1
+ local power_policy=$2
+ LOG_MSG "Device Model\t\t : $SSD_DEVICE_MODEL"
+ LOG_MSG "Serial Number\t\t : $SSD_SERIAL"
+ LOG_MSG "User Capacity\t\t : $SSD_SIZE GB"
+ LOG_MSG "Current Firmware Version : $SSD_FW_VER"
+ LOG_MSG "Available Firmware Version : $Newer_FW_Version"
+ LOG_MSG "Power Cycle Required\t : $power_policy"
+ LOG_MSG "Upgrade Required\t : yes"
+ elif [ $argument_count -eq 1 ]; then
+ local _upgrade_require=$1
+ LOG_MSG "Device Model\t : $SSD_DEVICE_MODEL"
+ LOG_MSG "Serial Number\t : $SSD_SERIAL"
+ LOG_MSG "User Capacity\t : $SSD_SIZE GB"
+ LOG_MSG "Firmware Version : $SSD_FW_VER"
+ LOG_MSG "Upgrade Required : $_upgrade_require"
+ else
+ LOG_MSG "Device Model\t : $SSD_DEVICE_MODEL"
+ LOG_MSG "Serial Number\t : $SSD_SERIAL"
+ LOG_MSG "User Capacity\t : $SSD_SIZE GB"
+ LOG_MSG "Firmware Version : $SSD_FW_VER"
+ fi
+}
+
+# Main
+# ------------------------------------------------------------------------------
+init_script
+check_usage "$@"
+
+# show help
+if [ $ARG_HELP_FLAG == $TRUE ]; then
+ usage
+ exit 0
+# show version
+elif [ $ARG_VERSION_FLAG == $TRUE ]; then
+ echo $UTIL_TITLE
+ exit 0
+# show SSD info
+elif [ $ARG_QUERY_FLAG == $TRUE ]; then
+ match_found=$FALSE
+ check_tool_dependencies
+ get_ssd_info
+
+ if [ $ARG_IMAGE_FLAG == $TRUE ]; then
+ extract_package $ARG_IMAGE_VAL extraction_path
+ ini_parser "$extraction_path/list.ini"
+
+ for section in $SECTIONS; do
+ if [[ $section != "main" ]]; then
+ call_ini_section $section
+ if [[ "$SSD_DEVICE_MODEL" == "$( IFS=$'\n'; echo "${SSD_FW_Model[@]}" )" ]] && \
+ [[ "$SSD_FW_VER" == "${SSD_FW_Version[@]}" ]] && \
+ [[ "$SSD_SIZE" == "${SSD_Size[@]}" ]]; then
+
+ match_found=$TRUE
+ break
+ fi
+ ini_unset $section
+ fi
+ done
+
+ erase_extract_package "$extraction_path"
+ if [[ "$match_found" == "$FALSE" ]]; then
+ #LOG_MSG "SSD FW upgrade not require, based on given package latest version is in used."
+ print_ssd_info "no"
+ echo -e ""
+ exit 0
+ fi
+ fi
+
+ if [[ "$match_found" == "$TRUE" ]]; then
+ print_ssd_info $Newer_FW_Version ${Shutdown_Policy[0],,}
+ erase_extract_package "$extraction_path"
+ else
+ print_ssd_info
+ fi
+
+ echo -e ""
+
+ exit 0
+# show package version
+elif [ $ARG_PACKAGE_INFO_FLAG == $TRUE ]; then
+ check_tool_dependencies
+ extract_package $ARG_IMAGE_VAL extraction_path
+ # 2. check signing
+ ini_parser "$extraction_path/list.ini"
+
+ call_ini_section "main"
+ LOG_MSG "Package Name: $ARG_IMAGE_VAL"
+ [[ ! -z ${description[@]} ]] && LOG_MSG "Description: ${description[@]}"
+ [[ ! -z ${version[@]} ]] && LOG_MSG "Version: ${version[@]}"
+ [[ ! -z ${release_date[@]} ]] && LOG_MSG "Release Date: ${release_date[@]}"
+ LOG_MSG "Supported SSDs:"
+ LOG_MSG " Vendor | Model | FW ver | Size | Pwr Cyc Req |"
+ LOG_MSG "=============|================================|==============|==========|=============|"
+ for section in $SECTIONS; do
+ if [[ "$section" != "main" ]]; then
+ call_ini_section $section
+ supported_model=$(string_supported_model $section)
+ LOG_MSG "$supported_model"
+ ini_unset $section
+ fi
+ done
+ echo -e ""
+ erase_extract_package "$extraction_path"
+ exit 0
+# operate SSD fw update
+elif [ $ARG_UPDATE_FLAG == $TRUE ]; then
+ check_tool_dependencies
+ get_ssd_info
+ extract_package $ARG_IMAGE_VAL extraction_path
+ # 2. check signing
+ UPDATE_DONE=$FALSE
+ ini_parser "$extraction_path/list.ini"
+ for section in $SECTIONS; do
+ if [[ $section != "main" ]]; then
+ call_ini_section $section
+ if [[ "$SSD_DEVICE_MODEL" == "$( IFS=$'\n'; echo "${SSD_FW_Model[@]}" )" ]] && \
+ [[ "$SSD_FW_VER" == "${SSD_FW_Version[@]}" ]] && \
+ [[ "$SSD_SIZE" == "${SSD_Size[@]}" ]]; then
+ UPDATE_DONE=$TRUE
+
+ power_policy=${Shutdown_Policy[0],,}
+ LOG_MSG "Power policy:$power_policy" ${DEBUG_MSG}
+ print_ssd_info $Newer_FW_Version ${Shutdown_Policy[0],,}
+ echo -e ""
+ #[[ "yes" == "$power_policy" ]] && LOG_MSG "PLEASE NOTE: System will power-cycle automatically once SSD FW Update complete!"
+ [[ "yes" == "$power_policy" || "$ARG_POWER_CYCLE_FLAG" == "$TRUE" ]] && LOG_MSG "Please note: Once SSD FW Update process ends, system will power-cycle automaticly and it will take up to 1 minute to access it back."
+
+ # Prompt approval for FW update if ignore in case "yes" flag is on.
+ if [[ "$ARG_YES_FLAG" == "$FALSE" ]]; then
+ read -p "Do you want to continue? [Y/N]" -n 1 -r
+ echo # (optional) move to a new line
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ LOG_MSG_AND_EXIT "Aborting..."
+ exit 0
+ fi
+ fi
+
+ # Check FWUpgrade scripts exists & if so call it.
+ ssd_script_name=$Update_Script
+ ssd_script_path="${extraction_path}/${section}/${ssd_script_name}"
+ LOG_MSG "ssd_script_path: $ssd_script_path" ${DEBUG_MSG}
+ if [ ! -f $ssd_script_path ]; then
+ LOG_MSG_AND_EXIT "Error: fail to call upgrade script ($ssd_script_path)!"
+ fi
+ (
+ cd "${extraction_path}/${section}" > /dev/null 2>&1 || exit
+ /bin/bash "$ssd_script_path" "${extraction_path}/${section}"
+ #cd - > /dev/null 2>&1 || exit
+ )
+ if [ $? -ne 0 ]; then
+ LOG_MSG_AND_EXIT "Error: SSD FW update failed."
+ else
+ LOG_MSG "SSD FW update completed successfully."
+
+ if [ $ARG_POWER_CYCLE_FLAG == $TRUE ]; then
+ LOG_MSG "Execute power cycle..."
+ sleep 1
+ sync
+ power_cycle_script="${extraction_path}/common/mlnx_shutdown.sh"
+ [ ! -f $power_cycle_script ]&& LOG_MSG_AND_EXIT "Error: failed to initiate power cycle."
+ ($power_cycle_script "-s")
+ [ $? -ne 0 ] && LOG_MSG_AND_EXIT "Error: failed to power cycle the system automatically."
+ erase_extract_package "$extraction_path"
+
+ fi
+
+ fi
+
+ break # Exit the for loop
+ fi
+ ini_unset $section
+ fi
+ done
+ if [ $UPDATE_DONE == $FALSE ]; then
+ LOG_MSG "SSD FW upgrade not require, based on given package latest version is in used."
+ print_ssd_info "no"
+ fi
+
+ echo -e ""
+ erase_extract_package "$extraction_path"
+ exit 0
+fi
+
+exit 0
diff --git a/platform/mellanox/one-image.mk b/platform/mellanox/one-image.mk
index 2946ae53f47b..0f69b7335bf1 100644
--- a/platform/mellanox/one-image.mk
+++ b/platform/mellanox/one-image.mk
@@ -11,5 +11,5 @@ $(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.g
else
$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES)
endif
-$(SONIC_ONE_IMAGE)_FILES += $(MLNX_SPC_FW_FILE) $(MLNX_SPC2_FW_FILE) $(MLNX_FFB_SCRIPT) $(ISSU_VERSION_FILE)
+$(SONIC_ONE_IMAGE)_FILES += $(MLNX_FILES)
SONIC_INSTALLERS += $(SONIC_ONE_IMAGE)
diff --git a/platform/mellanox/rules.mk b/platform/mellanox/rules.mk
index dd10cefda571..bdb4e955c2d4 100644
--- a/platform/mellanox/rules.mk
+++ b/platform/mellanox/rules.mk
@@ -12,6 +12,8 @@ include $(PLATFORM_PATH)/libsaithrift-dev.mk
include $(PLATFORM_PATH)/docker-ptf-mlnx.mk
include $(PLATFORM_PATH)/mlnx-ffb.mk
include $(PLATFORM_PATH)/issu-version.mk
+include $(PLATFORM_PATH)/mlnx-onie-fw-update.mk
+include $(PLATFORM_PATH)/mlnx-ssd-fw-update.mk
SONIC_ALL += $(SONIC_ONE_IMAGE) \
$(DOCKER_FPM)
diff --git a/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers b/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers
index c08b5bb3810f..1d7da850581f 160000
--- a/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers
+++ b/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers
@@ -1 +1 @@
-Subproject commit c08b5bb3810fe7da2811622aa7003ac9cc95344b
+Subproject commit 1d7da850581ff0dd79990ae1c5bcb174d4272267
diff --git a/platform/mellanox/sdk.mk b/platform/mellanox/sdk.mk
index 55a5b08bba31..3b2e9a8f30c8 100644
--- a/platform/mellanox/sdk.mk
+++ b/platform/mellanox/sdk.mk
@@ -1,5 +1,5 @@
MLNX_SDK_BASE_PATH = $(PLATFORM_PATH)/sdk-src/sx-kernel/Switch-SDK-drivers/bin/
-MLNX_SDK_VERSION = 4.3.2904
+MLNX_SDK_VERSION = 4.4.0880
MLNX_SDK_ISSU_VERSION = 101
MLNX_SDK_DEB_VERSION = $(subst _,.,$(MLNX_SDK_VERSION))
diff --git a/platform/nephos/docker-syncd-nephos-rpc.mk b/platform/nephos/docker-syncd-nephos-rpc.mk
index dafc43b3e7e3..39240c1913e4 100644
--- a/platform/nephos/docker-syncd-nephos-rpc.mk
+++ b/platform/nephos/docker-syncd-nephos-rpc.mk
@@ -2,7 +2,7 @@
DOCKER_SYNCD_NEPHOS_RPC = docker-syncd-nephos-rpc.gz
$(DOCKER_SYNCD_NEPHOS_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-nephos-rpc
-$(DOCKER_SYNCD_NEPHOS_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT)
+$(DOCKER_SYNCD_NEPHOS_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(PTF)
ifeq ($(INSTALL_DEBUG_TOOLS), y)
$(DOCKER_SYNCD_NEPHOS_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \
$(LIBSWSSCOMMON_DBG) \
diff --git a/platform/nephos/docker-syncd-nephos.mk b/platform/nephos/docker-syncd-nephos.mk
index 6829c91c67aa..67bad252870a 100644
--- a/platform/nephos/docker-syncd-nephos.mk
+++ b/platform/nephos/docker-syncd-nephos.mk
@@ -15,4 +15,4 @@ $(DOCKER_SYNCD_BASE)_RUN_OPT += -v /host/warmboot:/var/warmboot
$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd
$(DOCKER_SYNCD_BASE)_BASE_IMAGE_FILES += npx_diag:/usr/bin/npx_diag
-
+$(DOCKER_SYNCD_BASE)_BASE_IMAGE_FILES += monit_syncd:/etc/monit/conf.d
diff --git a/platform/nephos/docker-syncd-nephos/base_image_files/monit_syncd b/platform/nephos/docker-syncd-nephos/base_image_files/monit_syncd
new file mode 100644
index 000000000000..0b9ec741cd57
--- /dev/null
+++ b/platform/nephos/docker-syncd-nephos/base_image_files/monit_syncd
@@ -0,0 +1,11 @@
+###############################################################################
+## Monit configuration for syncd container
+## process list:
+## syncd
+## dsserve
+###############################################################################
+check process syncd matching "/usr/bin/syncd"
+ if does not exist for 5 times within 5 cycles then alert
+
+check process dsserve matching "/usr/bin/dsserve /usr/bin/syncd"
+ if does not exist for 5 times within 5 cycles then alert
diff --git a/platform/nephos/docker-syncd-nephos/supervisord.conf b/platform/nephos/docker-syncd-nephos/supervisord.conf
index c823ab5680ef..0c6285d46ae0 100644
--- a/platform/nephos/docker-syncd-nephos/supervisord.conf
+++ b/platform/nephos/docker-syncd-nephos/supervisord.conf
@@ -4,7 +4,7 @@ logfile_backups=2
nodaemon=true
[eventlistener:supervisor-proc-exit-listener]
-command=/usr/bin/supervisor-proc-exit-listener
+command=/usr/bin/supervisor-proc-exit-listener --container-name syncd
events=PROCESS_STATE_EXITED
autostart=true
autorestart=unexpected
diff --git a/platform/nephos/nephos-modules.mk b/platform/nephos/nephos-modules.mk
index b76141b40663..50a2d0e5c080 100644
--- a/platform/nephos/nephos-modules.mk
+++ b/platform/nephos/nephos-modules.mk
@@ -1,6 +1,6 @@
# Nephos Platform modules
-VERSION = 1.0.0
+VERSION = 1.0.1
ifneq ($(NEPHOS_SAI_DEB_LOCAL_URL), )
SDK_FROM_LOCAL = y
@@ -9,7 +9,7 @@ SDK_FROM_LOCAL = n
endif
SDK_VERSION = 3.0.0
-LINUX_VER = 4.9.0-9-2
+LINUX_VER = 4.9.0-11-2
SDK_COMMIT_ID = 529202
ifeq ($(SAI_FROM_LOCAL), y)
diff --git a/platform/nephos/nephos-modules/debian/changelog b/platform/nephos/nephos-modules/debian/changelog
index 3de2bd045efd..94c7aa7d3915 100644
--- a/platform/nephos/nephos-modules/debian/changelog
+++ b/platform/nephos/nephos-modules/debian/changelog
@@ -1,5 +1,11 @@
+nephos-modules (1.0.1) unstable; urgency=low
+
+ * Upgrade ko version to 3.0.0
+
+-- Support Tue, 17 Mar 2020 15:54:00 +0800
+
nephos-modules (1.0.0) unstable; urgency=low
* Initial release
- -- Support Fri, 15 Mar 2019 15:54:00 +0800
+-- Support Fri, 15 Mar 2019 15:54:00 +0800
diff --git a/platform/nephos/nephos-modules/debian/control b/platform/nephos/nephos-modules/debian/control
index f5e6e00d13c0..3d06ca971f89 100644
--- a/platform/nephos/nephos-modules/debian/control
+++ b/platform/nephos/nephos-modules/debian/control
@@ -1,12 +1,12 @@
Source: nephos-modules
Section: main
Priority: extra
-Maintainer: support
+Maintainer: support
Build-Depends: debhelper (>= 8.0.0), bzip2
Standards-Version: 3.9.3
Package: nephos-modules
Architecture: amd64
-Depends: linux-image-4.9.0-9-2-amd64
+Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for nephos asic
diff --git a/platform/nephos/nephos-modules/modules/init.d/nps-modules-4.9.0-9-2-amd64 b/platform/nephos/nephos-modules/modules/init.d/nps-modules-4.9-amd64
similarity index 92%
rename from platform/nephos/nephos-modules/modules/init.d/nps-modules-4.9.0-9-2-amd64
rename to platform/nephos/nephos-modules/modules/init.d/nps-modules-4.9-amd64
index 366ca6b08456..a6deb4217a95 100755
--- a/platform/nephos/nephos-modules/modules/init.d/nps-modules-4.9.0-9-2-amd64
+++ b/platform/nephos/nephos-modules/modules/init.d/nps-modules-4.9-amd64
@@ -45,7 +45,7 @@ force-reload|restart)
;;
*)
- echo "Usage: /etc/init.d/nps-modules-4.9.0-9-2-amd64.init {start|stop}"
+ echo "Usage: /etc/init.d/nps-modules-4.9.0-11-2-amd64.init {start|stop}"
exit 1
;;
esac
diff --git a/platform/nephos/nephos-modules/modules/service/nps-modules-4.9.0-9-2-amd64.service b/platform/nephos/nephos-modules/modules/service/nps-modules-4.9-amd64.service
similarity index 60%
rename from platform/nephos/nephos-modules/modules/service/nps-modules-4.9.0-9-2-amd64.service
rename to platform/nephos/nephos-modules/modules/service/nps-modules-4.9-amd64.service
index 246226ea9d40..fc45a597d74c 100644
--- a/platform/nephos/nephos-modules/modules/service/nps-modules-4.9.0-9-2-amd64.service
+++ b/platform/nephos/nephos-modules/modules/service/nps-modules-4.9-amd64.service
@@ -5,8 +5,8 @@ Before=syncd.service
[Service]
Type=oneshot
-ExecStart=-/etc/init.d/nps-modules-4.9.0-9-2-amd64 start
-ExecStop=-/etc/init.d/nps-modules-4.9.0-9-2-amd64 stop
+ExecStart=-/etc/init.d/nps-modules-4.9-amd64 start
+ExecStop=-/etc/init.d/nps-modules-4.9-amd64 stop
RemainAfterExit=yes
[Install]
diff --git a/platform/nephos/nephos-modules/modules/src/hal_tau_pkt_knl.c b/platform/nephos/nephos-modules/modules/src/hal_tau_pkt_knl.c
index b386da63e247..a67b1d5f8868 100755
--- a/platform/nephos/nephos-modules/modules/src/hal_tau_pkt_knl.c
+++ b/platform/nephos/nephos-modules/modules/src/hal_tau_pkt_knl.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -45,6 +45,9 @@
/* netif */
#include
#include
+#if defined(NETIF_EN_NETLINK)
+#include
+#endif
#include
/* nps_sdk */
@@ -69,19 +72,20 @@
/* This flag value will be specified when user inserts kernel module. */
-#define HAL_TAU_PKT_DBG_ERR (0x1 << 0)
-#define HAL_TAU_PKT_DBG_TX (0x1 << 1)
-#define HAL_TAU_PKT_DBG_RX (0x1 << 2)
-#define HAL_TAU_PKT_DBG_INTF (0x1 << 3)
-#define HAL_TAU_PKT_DBG_PROFILE (0x1 << 4)
-#define HAL_TAU_PKT_DBG_COMMON (0x1 << 5)
+#define HAL_TAU_PKT_DBG_ERR (0x1UL << 0)
+#define HAL_TAU_PKT_DBG_TX (0x1UL << 1)
+#define HAL_TAU_PKT_DBG_RX (0x1UL << 2)
+#define HAL_TAU_PKT_DBG_INTF (0x1UL << 3)
+#define HAL_TAU_PKT_DBG_PROFILE (0x1UL << 4)
+#define HAL_TAU_PKT_DBG_COMMON (0x1UL << 5)
+#define HAL_TAU_PKT_DBG_NETLINK (0x1UL << 6)
/* Will be set when inserting kernel module */
-static UI32_T dbg_flag = 0;
+UI32_T ext_dbg_flag = 0;
#define HAL_TAU_PKT_DBG(__flag__, ...) do \
{ \
- if (0 != ((__flag__) & (dbg_flag))) \
+ if (0 != ((__flag__) & (ext_dbg_flag))) \
{ \
osal_printf(__VA_ARGS__); \
} \
@@ -113,15 +117,15 @@ typedef struct
static HAL_TAU_PKT_INTR_VEC_T _hal_tau_pkt_intr_vec[] =
{
- { /* 0: PDMA_ERR */ 1 << 0, 0x0, 0 },
- { /* 1: TX_CH0 */ 1 << 28, 0x0, 0 },
- { /* 2: TX_CH1 */ 1 << 29, 0x0, 0 },
- { /* 3: TX_CH2 */ 1 << 30, 0x0, 0 },
- { /* 4: TX_CH3 */ 1 << 31, 0x0, 0 },
- { /* 5: RX_CH0 */ 1 << 12, 0x0, 0 },
- { /* 6: RX_CH1 */ 1 << 13, 0x0, 0 },
- { /* 7: RX_CH2 */ 1 << 14, 0x0, 0 },
- { /* 8: RX_CH3 */ 1 << 15, 0x0, 0 },
+ { /* 0: PDMA_ERR */ 1UL << 0, 0x0, 0 },
+ { /* 1: TX_CH0 */ 1UL << 28, 0x0, 0 },
+ { /* 2: TX_CH1 */ 1UL << 29, 0x0, 0 },
+ { /* 3: TX_CH2 */ 1UL << 30, 0x0, 0 },
+ { /* 4: TX_CH3 */ 1UL << 31, 0x0, 0 },
+ { /* 5: RX_CH0 */ 1UL << 12, 0x0, 0 },
+ { /* 6: RX_CH1 */ 1UL << 13, 0x0, 0 },
+ { /* 7: RX_CH2 */ 1UL << 14, 0x0, 0 },
+ { /* 8: RX_CH3 */ 1UL << 15, 0x0, 0 },
};
/*****************************************************************************
@@ -136,9 +140,10 @@ static HAL_TAU_PKT_INTR_VEC_T _hal_tau_pkt_intr_vec[] =
#define HAL_TAU_PKT_ALLOC_MEM_RETRY_SLEEP() osal_sleepThread(1000) /* us */
/* Network Device Definitions */
-#define HAL_TAU_PKT_TX_TIMEOUT (6*HZ)
+/* In case that the watchdog alarm during warm-boot if intf isn't killed */
+#define HAL_TAU_PKT_TX_TIMEOUT (30*HZ)
#define HAL_TAU_PKT_MAX_ETH_FRAME_SIZE (HAL_TAU_PKT_RX_MAX_LEN)
-#define HAL_TAU_PKT_MAX_PORT_NUM (HAL_TAU_PORT_NUM + 1) /* CPU port */
+#define HAL_TAU_PKT_MAX_PORT_NUM (HAL_PORT_NUM + 1) /* CPU port */
#define HAL_TAU_PKT_NET_PROFILE_NUM_MAX (256)
@@ -199,10 +204,10 @@ typedef struct
NPS_ISRLOCK_ID_T intr_lock;
UI32_T intr_bitmap;
-#define HAL_TAU_PKT_INIT_DRV (1 << 0)
-#define HAL_TAU_PKT_INIT_TASK (1 << 1)
-#define HAL_TAU_PKT_INIT_INTR (1 << 2)
-#define HAL_TAU_PKT_INIT_RX_START (1 << 3)
+#define HAL_TAU_PKT_INIT_DRV (1UL << 0)
+#define HAL_TAU_PKT_INIT_TASK (1UL << 1)
+#define HAL_TAU_PKT_INIT_INTR (1UL << 2)
+#define HAL_TAU_PKT_INIT_RX_START (1UL << 3)
/* a bitmap to record the init status */
UI32_T init_flag;
@@ -255,6 +260,10 @@ typedef struct
BOOL_T running; /* TRUE when Init txTask
* FALSE when Destroy txTask
*/
+ /* to block net intf Tx in driver level since netif_tx_disable()
+ * cannot always prevent intf from Tx in time
+ */
+ BOOL_T net_tx_allowed;
} HAL_TAU_PKT_TX_CB_T;
@@ -312,6 +321,9 @@ typedef enum
{
HAL_TAU_PKT_DEST_NETDEV = 0,
HAL_TAU_PKT_DEST_SDK,
+#if defined(NETIF_EN_NETLINK)
+ HAL_TAU_PKT_DEST_NETLINK,
+#endif
HAL_TAU_PKT_DEST_DROP,
HAL_TAU_PKT_DEST_LAST
} HAL_TAU_PKT_DEST_T;
@@ -1215,7 +1227,158 @@ hal_tau_pkt_setPortAttr(
return (NPS_E_OK);
}
+static void
+_hal_tau_pkt_lockRxChannelAll(
+ const UI32_T unit)
+{
+ UI32_T rch;
+ HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma;
+
+ for (rch = 0; rch < HAL_TAU_PKT_RX_CHANNEL_LAST; rch++)
+ {
+ ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, rch);
+ osal_takeSemaphore(&ptr_rx_pdma->sema, NPS_SEMAPHORE_WAIT_FOREVER);
+ }
+}
+
+static void
+_hal_tau_pkt_unlockRxChannelAll(
+ const UI32_T unit)
+{
+ UI32_T rch;
+ HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma;
+
+ for (rch = 0; rch < HAL_TAU_PKT_RX_CHANNEL_LAST; rch++)
+ {
+ ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, rch);
+ osal_giveSemaphore(&ptr_rx_pdma->sema);
+ }
+}
+
+#if defined(NETIF_EN_NETLINK)
+
+static NPS_ERROR_NO_T
+_hal_tau_pkt_setIntfProperty(
+ const UI32_T unit,
+ HAL_TAU_PKT_NL_IOCTL_COOKIE_T *ptr_cookie)
+{
+ UI32_T intf_id;
+ NETIF_NL_INTF_PROPERTY_T property;
+ UI32_T param0;
+ UI32_T param1;
+ NPS_ERROR_NO_T rc;
+
+ osal_io_copyFromUser(&intf_id, &ptr_cookie->intf_id, sizeof(UI32_T));
+ osal_io_copyFromUser(&property, &ptr_cookie->property, sizeof(NETIF_NL_INTF_PROPERTY_T));
+ osal_io_copyFromUser(¶m0, &ptr_cookie->param0, sizeof(UI32_T));
+ osal_io_copyFromUser(¶m1, &ptr_cookie->param1, sizeof(UI32_T));
+
+ _hal_tau_pkt_lockRxChannelAll(unit);
+
+ rc = netif_nl_setIntfProperty(unit, intf_id, property, param0, param1);
+
+ _hal_tau_pkt_unlockRxChannelAll(unit);
+
+ osal_io_copyToUser(&ptr_cookie->rc, &rc, sizeof(NPS_ERROR_NO_T));
+
+ return (rc);
+}
+
+static NPS_ERROR_NO_T
+_hal_tau_pkt_getIntfProperty(
+ const UI32_T unit,
+ HAL_TAU_PKT_NL_IOCTL_COOKIE_T *ptr_cookie)
+{
+ UI32_T intf_id;
+ NETIF_NL_INTF_PROPERTY_T property;
+ UI32_T param0;
+ UI32_T param1;
+ NPS_ERROR_NO_T rc;
+
+ osal_io_copyFromUser(&intf_id, &ptr_cookie->intf_id, sizeof(UI32_T));
+ osal_io_copyFromUser(&property, &ptr_cookie->property, sizeof(NETIF_NL_INTF_PROPERTY_T));
+ osal_io_copyFromUser(¶m0, &ptr_cookie->param0, sizeof(UI32_T));
+
+ rc = netif_nl_getIntfProperty(unit, intf_id, property, ¶m0, ¶m1);
+
+ osal_io_copyToUser(&ptr_cookie->param0, ¶m0, sizeof(UI32_T));
+ osal_io_copyToUser(&ptr_cookie->param1, ¶m1, sizeof(UI32_T));
+ osal_io_copyToUser(&ptr_cookie->rc, &rc, sizeof(NPS_ERROR_NO_T));
+
+ return (rc);
+}
+
+static NPS_ERROR_NO_T
+_hal_tau_pkt_createNetlink(
+ const UI32_T unit,
+ HAL_TAU_PKT_NL_IOCTL_COOKIE_T *ptr_cookie)
+{
+ NETIF_NL_NETLINK_T netlink;
+ UI32_T netlink_id;
+ NPS_ERROR_NO_T rc;
+
+ osal_io_copyFromUser(&netlink, &ptr_cookie->netlink, sizeof(NETIF_NL_NETLINK_T));
+
+ _hal_tau_pkt_lockRxChannelAll(unit);
+
+ rc = netif_nl_createNetlink(unit, &netlink, &netlink_id);
+
+ _hal_tau_pkt_unlockRxChannelAll(unit);
+
+ osal_io_copyToUser(&ptr_cookie->netlink.id, &netlink_id, sizeof(UI32_T));
+ osal_io_copyToUser(&ptr_cookie->rc, &rc, sizeof(NPS_ERROR_NO_T));
+
+ return (rc);
+}
+
+static NPS_ERROR_NO_T
+_hal_tau_pkt_destroyNetlink(
+ const UI32_T unit,
+ HAL_TAU_PKT_NL_IOCTL_COOKIE_T *ptr_cookie)
+{
+ UI32_T netlink_id;
+ NPS_ERROR_NO_T rc;
+
+ osal_io_copyFromUser(&netlink_id, &ptr_cookie->netlink.id, sizeof(UI32_T));
+
+ _hal_tau_pkt_lockRxChannelAll(unit);
+
+ rc = netif_nl_destroyNetlink(unit, netlink_id);
+
+ _hal_tau_pkt_unlockRxChannelAll(unit);
+
+ osal_io_copyToUser(&ptr_cookie->rc, &rc, sizeof(NPS_ERROR_NO_T));
+
+ return (rc);
+}
+
+static NPS_ERROR_NO_T
+_hal_tau_pkt_getNetlink(
+ const UI32_T unit,
+ HAL_TAU_PKT_NL_IOCTL_COOKIE_T *ptr_cookie)
+{
+ UI32_T id;
+ NETIF_NL_NETLINK_T netlink;
+ NPS_ERROR_NO_T rc;
+ osal_io_copyFromUser(&id, &ptr_cookie->netlink.id, sizeof(UI32_T));
+
+ rc = netif_nl_getNetlink(unit, id, &netlink);
+ if (NPS_E_OK == rc)
+ {
+ osal_io_copyToUser(&ptr_cookie->netlink, &netlink, sizeof(NETIF_NL_NETLINK_T));
+ }
+ else
+ {
+ rc = NPS_E_ENTRY_NOT_FOUND;
+ }
+
+ osal_io_copyToUser(&ptr_cookie->rc, &rc, sizeof(NPS_ERROR_NO_T));
+
+ return (NPS_E_OK);
+}
+
+#endif
/* ----------------------------------------------------------------------------------- independent func */
/* FUNCTION NAME: _hal_tau_pkt_enQueue
* PURPOSE:
@@ -1877,7 +2040,7 @@ _hal_tau_pkt_rxCheckReason(
HAL_TAU_PKT_NETIF_PROFILE_T *ptr_profile,
BOOL_T *ptr_hit_prof)
{
- HAL_TAU_PKT_RX_REASON_BITMAP_T *ptr_reason_bitmap = &ptr_profile->reason_bitmap;
+ HAL_PKT_RX_REASON_BITMAP_T *ptr_reason_bitmap = &ptr_profile->reason_bitmap;
UI32_T bitval = 0;
UI32_T bitmap = 0x0;
@@ -1888,10 +2051,10 @@ _hal_tau_pkt_rxCheckReason(
return;
}
-#define HAL_TAU_PKT_DI_NON_L3_CPU_MIN (HAL_TAU_EXCPT_CPU_BASE_ID + HAL_TAU_EXCPT_CPU_NON_L3_MIN)
-#define HAL_TAU_PKT_DI_NON_L3_CPU_MAX (HAL_TAU_EXCPT_CPU_BASE_ID + HAL_TAU_EXCPT_CPU_NON_L3_MAX)
-#define HAL_TAU_PKT_DI_L3_CPU_MIN (HAL_TAU_EXCPT_CPU_BASE_ID + HAL_TAU_EXCPT_CPU_L3_MIN)
-#define HAL_TAU_PKT_DI_L3_CPU_MAX (HAL_TAU_EXCPT_CPU_BASE_ID + HAL_TAU_EXCPT_CPU_L3_MAX)
+#define HAL_TAU_PKT_DI_NON_L3_CPU_MIN (HAL_EXCPT_CPU_BASE_ID + HAL_EXCPT_CPU_NON_L3_MIN)
+#define HAL_TAU_PKT_DI_NON_L3_CPU_MAX (HAL_EXCPT_CPU_BASE_ID + HAL_EXCPT_CPU_NON_L3_MAX)
+#define HAL_TAU_PKT_DI_L3_CPU_MIN (HAL_EXCPT_CPU_BASE_ID + HAL_EXCPT_CPU_L3_MIN)
+#define HAL_TAU_PKT_DI_L3_CPU_MAX (HAL_EXCPT_CPU_BASE_ID + HAL_EXCPT_CPU_L3_MAX)
switch (ptr_rx_gpd->itmh_eth.typ)
{
@@ -1902,7 +2065,7 @@ _hal_tau_pkt_rxCheckReason(
ptr_rx_gpd->itmh_eth.dst_idx <= HAL_TAU_PKT_DI_NON_L3_CPU_MAX)
{
bitval = ptr_rx_gpd->itmh_eth.dst_idx - HAL_TAU_PKT_DI_NON_L3_CPU_MIN;
- bitmap = 1 << (bitval % 32);
+ bitmap = 1UL << (bitval % 32);
if (0 != (ptr_reason_bitmap->ipp_excpt_bitmap[bitval / 32] & bitmap))
{
*ptr_hit_prof = TRUE;
@@ -1932,7 +2095,7 @@ _hal_tau_pkt_rxCheckReason(
/* IPP cp_to_cpu_rsn */
bitval = ptr_rx_gpd->itmh_eth.cp_to_cpu_code;
- bitmap = 1 << (bitval % 32);
+ bitmap = 1UL << (bitval % 32);
if (0 != (ptr_reason_bitmap->ipp_rsn_bitmap[bitval / 32] & bitmap))
{
*ptr_hit_prof = TRUE;
@@ -1950,7 +2113,7 @@ _hal_tau_pkt_rxCheckReason(
if (1 == ptr_rx_gpd->etmh_eth.redir)
{
bitval = ptr_rx_gpd->etmh_eth.excpt_code_mir_bmap;
- bitmap = 1 << (bitval % 32);
+ bitmap = 1UL << (bitval % 32);
if (0 != (ptr_reason_bitmap->epp_excpt_bitmap[bitval / 32] & bitmap))
{
*ptr_hit_prof = TRUE;
@@ -2059,25 +2222,30 @@ static void
_hal_tau_pkt_matchUserProfile(
volatile HAL_TAU_PKT_RX_GPD_T *ptr_rx_gpd,
HAL_TAU_PKT_PROFILE_NODE_T *ptr_profile_list,
- BOOL_T *ptr_hit_prof)
+ HAL_TAU_PKT_NETIF_PROFILE_T **pptr_profile_hit)
{
HAL_TAU_PKT_PROFILE_NODE_T *ptr_curr_node = ptr_profile_list;
+ BOOL_T hit;
+
+ *pptr_profile_hit = NULL;
while (NULL != ptr_curr_node)
{
/* 1st match reason */
- _hal_tau_pkt_rxCheckReason(ptr_rx_gpd, ptr_curr_node->ptr_profile, ptr_hit_prof);
- if (TRUE == *ptr_hit_prof)
+ _hal_tau_pkt_rxCheckReason(ptr_rx_gpd, ptr_curr_node->ptr_profile, &hit);
+ if (TRUE == hit)
{
HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE,
"rx prof matched by reason\n");
/* Then, check pattern */
- _hal_tau_pkt_rxCheckPattern(ptr_rx_gpd, ptr_curr_node->ptr_profile, ptr_hit_prof);
- if (TRUE == *ptr_hit_prof)
+ _hal_tau_pkt_rxCheckPattern(ptr_rx_gpd, ptr_curr_node->ptr_profile, &hit);
+ if (TRUE == hit)
{
HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE,
"rx prof matched by pattern\n");
+
+ *pptr_profile_hit = ptr_curr_node->ptr_profile;
break;
}
}
@@ -2090,19 +2258,34 @@ _hal_tau_pkt_matchUserProfile(
static void
_hal_tau_pkt_getPacketDest(
volatile HAL_TAU_PKT_RX_GPD_T *ptr_rx_gpd,
- HAL_TAU_PKT_DEST_T *ptr_dest)
+ HAL_TAU_PKT_DEST_T *ptr_dest,
+ void **pptr_cookie)
{
- BOOL_T hit_prof = FALSE;
UI32_T port;
HAL_TAU_PKT_PROFILE_NODE_T *ptr_profile_list;
+ HAL_TAU_PKT_NETIF_PROFILE_T *ptr_profile_hit;
port = ptr_rx_gpd->itmh_eth.igr_phy_port;
ptr_profile_list = HAL_TAU_PKT_GET_PORT_PROFILE_LIST(port);
- _hal_tau_pkt_matchUserProfile(ptr_rx_gpd, ptr_profile_list, &hit_prof);
- if (TRUE == hit_prof)
+ _hal_tau_pkt_matchUserProfile(ptr_rx_gpd,
+ ptr_profile_list,
+ &ptr_profile_hit);
+ if (NULL != ptr_profile_hit)
{
+#if defined(NETIF_EN_NETLINK)
+ if (HAL_TAU_PKT_NETIF_RX_DST_NETLINK == ptr_profile_hit->dst_type)
+ {
+ *ptr_dest = HAL_TAU_PKT_DEST_NETLINK;
+ *pptr_cookie = (void *)&ptr_profile_hit->netlink;
+ }
+ else
+ {
+ *ptr_dest = HAL_TAU_PKT_DEST_SDK;
+ }
+#else
*ptr_dest = HAL_TAU_PKT_DEST_SDK;
+#endif
}
else
{
@@ -2134,7 +2317,7 @@ _hal_tau_pkt_rxEnQueue(
HAL_TAU_PKT_RX_SW_GPD_T *ptr_sw_first_gpd = ptr_sw_gpd;
void *ptr_virt_addr = NULL;
NPS_ADDR_T phy_addr = 0;
- HAL_TAU_PKT_DEST_T pkt_dest;
+ HAL_TAU_PKT_DEST_T dest_type;
/* skb meta */
UI32_T port = 0, len = 0, total_len = 0;
@@ -2142,6 +2325,7 @@ _hal_tau_pkt_rxEnQueue(
struct net_device_priv *ptr_priv = NULL;
struct sk_buff *ptr_skb = NULL, *ptr_merge_skb = NULL;
UI32_T copy_offset;
+ void *ptr_dest;
#if defined(PERF_EN_TEST)
/* To verify kernel Rx performance */
@@ -2166,9 +2350,16 @@ _hal_tau_pkt_rxEnQueue(
}
#endif
- _hal_tau_pkt_getPacketDest(&ptr_sw_gpd->rx_gpd, &pkt_dest);
- if (HAL_TAU_PKT_DEST_NETDEV == pkt_dest)
+ _hal_tau_pkt_getPacketDest(&ptr_sw_gpd->rx_gpd, &dest_type, &ptr_dest);
+
+#if defined(NETIF_EN_NETLINK)
+ if ((HAL_TAU_PKT_DEST_NETDEV == dest_type) ||
+ (HAL_TAU_PKT_DEST_NETLINK == dest_type))
+#else
+ if (HAL_TAU_PKT_DEST_NETDEV == dest_type)
+#endif
{
+ /* need to encap the packet as skb */
ptr_sw_gpd = ptr_sw_first_gpd;
while (NULL != ptr_sw_gpd)
{
@@ -2205,6 +2396,9 @@ _hal_tau_pkt_rxEnQueue(
ptr_sw_gpd = ptr_sw_gpd->ptr_next;
}
+ port = ptr_sw_first_gpd->rx_gpd.itmh_eth.igr_phy_port;
+ ptr_net_dev = HAL_TAU_PKT_GET_PORT_NETDEV(port);
+
/* if the packet is composed of multiple gpd (skb), need to merge it into a single skb */
if (NULL != ptr_sw_first_gpd->ptr_next)
{
@@ -2247,10 +2441,6 @@ _hal_tau_pkt_rxEnQueue(
_hal_tau_pkt_freeRxGpdList(unit, ptr_sw_first_gpd, FALSE);
}
- /* get port and net_device */
- port = ptr_sw_first_gpd->rx_gpd.itmh_eth.igr_phy_port;
- ptr_net_dev = HAL_TAU_PKT_GET_PORT_NETDEV(port);
-
/* if NULL netdev, drop the skb */
if (NULL == ptr_net_dev)
{
@@ -2265,19 +2455,33 @@ _hal_tau_pkt_rxEnQueue(
/* skb handling */
ptr_skb->dev = ptr_net_dev;
ptr_skb->pkt_type = PACKET_HOST; /* this packet is for me */
- ptr_skb->protocol = eth_type_trans(ptr_skb, ptr_net_dev); /* skip ethernet header */
ptr_skb->ip_summed = CHECKSUM_UNNECESSARY; /* skip checksum */
/* send to linux */
- osal_skb_recv(ptr_skb);
+ if (dest_type == HAL_TAU_PKT_DEST_NETDEV)
+ {
+ /* skip ethernet header only for Linux net interface*/
+ ptr_skb->protocol = eth_type_trans(ptr_skb, ptr_net_dev);
+ osal_skb_recv(ptr_skb);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
- ptr_net_dev->last_rx = jiffies;
+ ptr_net_dev->last_rx = jiffies;
+#endif
+ ptr_priv = netdev_priv(ptr_net_dev);
+ ptr_priv->stats.rx_packets++;
+ ptr_priv->stats.rx_bytes += total_len;
+ }
+#if defined(NETIF_EN_NETLINK)
+ else
+ {
+ HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE,
+ "hit profile dest=netlink, name=%s, mcgrp=%s\n",
+ ((NETIF_NL_RX_DST_NETLINK_T *)ptr_dest)->name,
+ ((NETIF_NL_RX_DST_NETLINK_T *)ptr_dest)->mc_group_name);
+ netif_nl_rxSkb(unit, ptr_skb, ptr_dest);
+ }
#endif
- ptr_priv = netdev_priv(ptr_net_dev);
- ptr_priv->stats.rx_packets++;
- ptr_priv->stats.rx_bytes += total_len;
}
- else if (HAL_TAU_PKT_DEST_SDK == pkt_dest)
+ else if (HAL_TAU_PKT_DEST_SDK == dest_type)
{
while (0 != _hal_tau_pkt_enQueue(&ptr_rx_cb->sw_queue[channel], ptr_sw_gpd))
{
@@ -2289,7 +2493,7 @@ _hal_tau_pkt_rxEnQueue(
osal_triggerEvent(&ptr_rx_cb->sync_sema);
ptr_rx_cb->cnt.channel[channel].trig_event++;
}
- else if (HAL_TAU_PKT_DEST_DROP == pkt_dest)
+ else if (HAL_TAU_PKT_DEST_DROP == dest_type)
{
_hal_tau_pkt_freeRxGpdList(unit, ptr_sw_first_gpd, TRUE);
}
@@ -2297,10 +2501,34 @@ _hal_tau_pkt_rxEnQueue(
{
HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_RX),
"u=%u, rxch=%u, invalid pkt dest=%d\n",
- unit, channel, pkt_dest);
+ unit, channel, dest_type);
}
}
+static NPS_ERROR_NO_T
+_hal_tau_pkt_flushRxQueue(
+ const UI32_T unit,
+ HAL_TAU_PKT_SW_QUEUE_T *ptr_que)
+{
+ HAL_TAU_PKT_RX_SW_GPD_T *ptr_sw_gpd_knl = NULL;
+ NPS_ERROR_NO_T rc;
+
+ while (1)
+ {
+ rc = _hal_tau_pkt_deQueue(ptr_que, (void **)&ptr_sw_gpd_knl);
+ if (NPS_E_OK == rc)
+ {
+ _hal_tau_pkt_freeRxGpdList(unit, ptr_sw_gpd_knl, TRUE);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return (NPS_E_OK);
+}
+
/* FUNCTION NAME: _hal_tau_pkt_schedRxDeQueue
* PURPOSE:
* To dequeue the packets based on the configured algorithm.
@@ -2335,33 +2563,14 @@ _hal_tau_pkt_schedRxDeQueue(
UI32_T buf_len = 0;
NPS_ERROR_NO_T rc = NPS_E_OK;
- /* get queue and count */
- for (idx = 0; idx < HAL_TAU_PKT_RX_QUEUE_NUM; idx++)
- {
- /* to gurantee the opportunity where each queue can be handler */
- queue = ((ptr_rx_cb->deque_idx + idx) % HAL_TAU_PKT_RX_QUEUE_NUM);
- _hal_tau_pkt_getQueueCount(&ptr_rx_cb->sw_queue[queue], &que_cnt);
- if (que_cnt > 0)
- {
- ptr_rx_cb->deque_idx = ((queue + 1) % HAL_TAU_PKT_RX_QUEUE_NUM);
- break;
- }
- }
-
- /* If all of the queues are empty, wait rxTask event */
- if (0 == que_cnt)
+ /* normal process */
+ if (TRUE == ptr_rx_cb->running)
{
- osal_waitEvent(&ptr_rx_cb->sync_sema);
- if (FALSE == ptr_rx_cb->running)
- {
- return (NPS_E_OTHERS); /* deinit */
- }
-
- ptr_rx_cb->cnt.wait_event++;
-
- /* re-get queue and count */
- for (queue = 0; queue < HAL_TAU_PKT_RX_QUEUE_NUM; queue++)
+ /* get queue and count */
+ for (idx = 0; idx < HAL_TAU_PKT_RX_QUEUE_NUM; idx++)
{
+ /* to gurantee the opportunity where each queue can be handler */
+ queue = ((ptr_rx_cb->deque_idx + idx) % HAL_TAU_PKT_RX_QUEUE_NUM);
_hal_tau_pkt_getQueueCount(&ptr_rx_cb->sw_queue[queue], &que_cnt);
if (que_cnt > 0)
{
@@ -2369,68 +2578,87 @@ _hal_tau_pkt_schedRxDeQueue(
break;
}
}
- }
- /* deque */
- if ((que_cnt > 0) && (queue < HAL_TAU_PKT_RX_QUEUE_NUM))
- {
- rc = _hal_tau_pkt_deQueue(&ptr_rx_cb->sw_queue[queue], (void **)&ptr_sw_gpd_knl);
- if (NPS_E_OK == rc)
+ /* If all of the queues are empty, wait rxTask event */
+ if (0 == que_cnt)
{
- ptr_rx_cb->cnt.channel[queue].deque_ok++;
- ptr_sw_first_gpd_knl = ptr_sw_gpd_knl;
+ osal_waitEvent(&ptr_rx_cb->sync_sema);
- osal_io_copyFromUser(&ioctl_data, ptr_cookie, sizeof(HAL_TAU_PKT_IOCTL_RX_COOKIE_T));
+ ptr_rx_cb->cnt.wait_event++;
- while (NULL != ptr_sw_gpd_knl)
+ /* re-get queue and count */
+ for (queue = 0; queue < HAL_TAU_PKT_RX_QUEUE_NUM; queue++)
{
- /* get the IOCTL GPD from user */
- osal_io_copyFromUser(&ioctl_gpd,
- ((void *)((NPS_HUGE_T)ioctl_data.ioctl_gpd_addr))
- + gpd_idx*sizeof(HAL_TAU_PKT_IOCTL_RX_GPD_T),
- sizeof(HAL_TAU_PKT_IOCTL_RX_GPD_T));
+ _hal_tau_pkt_getQueueCount(&ptr_rx_cb->sw_queue[queue], &que_cnt);
+ if (que_cnt > 0)
+ {
+ ptr_rx_cb->deque_idx = ((queue + 1) % HAL_TAU_PKT_RX_QUEUE_NUM);
+ break;
+ }
+ }
+ }
- /* get knl buf addr */
- ptr_rx_gpd = &ptr_sw_gpd_knl->rx_gpd;
- phy_addr = NPS_ADDR_32_TO_64(ptr_rx_gpd->data_buf_addr_hi, ptr_rx_gpd->data_buf_addr_lo);
+ /* deque */
+ if ((que_cnt > 0) && (queue < HAL_TAU_PKT_RX_QUEUE_NUM))
+ {
+ rc = _hal_tau_pkt_deQueue(&ptr_rx_cb->sw_queue[queue], (void **)&ptr_sw_gpd_knl);
+ if (NPS_E_OK == rc)
+ {
+ ptr_rx_cb->cnt.channel[queue].deque_ok++;
+ ptr_sw_first_gpd_knl = ptr_sw_gpd_knl;
- ptr_virt_addr = ptr_sw_gpd_knl->ptr_cookie;
- osal_skb_unmapDma(phy_addr, ((struct sk_buff *)ptr_virt_addr)->len, DMA_FROM_DEVICE);
+ osal_io_copyFromUser(&ioctl_data, ptr_cookie, sizeof(HAL_TAU_PKT_IOCTL_RX_COOKIE_T));
- buf_len = (HAL_TAU_PKT_CH_LAST_GPD == ptr_rx_gpd->ch)?
- ptr_rx_gpd->cnsm_buf_len : ptr_rx_gpd->avbl_buf_len;
+ while (NULL != ptr_sw_gpd_knl)
+ {
+ /* get the IOCTL GPD from user */
+ osal_io_copyFromUser(&ioctl_gpd,
+ ((void *)((NPS_HUGE_T)ioctl_data.ioctl_gpd_addr))
+ + gpd_idx*sizeof(HAL_TAU_PKT_IOCTL_RX_GPD_T),
+ sizeof(HAL_TAU_PKT_IOCTL_RX_GPD_T));
+
+ /* get knl buf addr */
+ ptr_rx_gpd = &ptr_sw_gpd_knl->rx_gpd;
+ phy_addr = NPS_ADDR_32_TO_64(ptr_rx_gpd->data_buf_addr_hi, ptr_rx_gpd->data_buf_addr_lo);
+
+ ptr_virt_addr = ptr_sw_gpd_knl->ptr_cookie;
+ osal_skb_unmapDma(phy_addr, ((struct sk_buff *)ptr_virt_addr)->len, DMA_FROM_DEVICE);
+
+ buf_len = (HAL_TAU_PKT_CH_LAST_GPD == ptr_rx_gpd->ch)?
+ ptr_rx_gpd->cnsm_buf_len : ptr_rx_gpd->avbl_buf_len;
+
+ /* overwrite whole rx_gpd to user
+ * the user should re-assign the correct value to data_buf_addr_hi, data_buf_addr_low
+ * after this IOCTL returns
+ */
+ osal_io_copyToUser((void *)((NPS_HUGE_T)ioctl_gpd.hw_gpd_addr),
+ &ptr_sw_gpd_knl->rx_gpd,
+ sizeof(HAL_TAU_PKT_RX_GPD_T));
+ /* copy buf */
+ /* DMA buf address allocated by the user is store in ptr_ioctl_data->gpd[idx].cookie */
+ osal_io_copyToUser((void *)((NPS_HUGE_T)ioctl_gpd.dma_buf_addr),
+ ((struct sk_buff *)ptr_virt_addr)->data, buf_len);
+ ptr_sw_gpd_knl->ptr_cookie = ptr_virt_addr;
+
+ /* next */
+ ptr_sw_gpd_knl = ptr_sw_gpd_knl->ptr_next;
+ gpd_idx++;
+ }
- /* overwrite whole rx_gpd to user
- * the user should re-assign the correct value to data_buf_addr_hi, data_buf_addr_low
- * after this IOCTL returns
- */
- osal_io_copyToUser((void *)((NPS_HUGE_T)ioctl_gpd.hw_gpd_addr),
- &ptr_sw_gpd_knl->rx_gpd,
- sizeof(HAL_TAU_PKT_RX_GPD_T));
- /* copy buf */
- /* DMA buf address allocated by the user is store in ptr_ioctl_data->gpd[idx].cookie */
- osal_io_copyToUser((void *)((NPS_HUGE_T)ioctl_gpd.dma_buf_addr),
- ((struct sk_buff *)ptr_virt_addr)->data, buf_len);
- ptr_sw_gpd_knl->ptr_cookie = ptr_virt_addr;
-
- /* next */
- ptr_sw_gpd_knl = ptr_sw_gpd_knl->ptr_next;
- gpd_idx++;
+ /* Must free kernel sw_gpd */
+ _hal_tau_pkt_freeRxGpdList(unit, ptr_sw_first_gpd_knl, TRUE);
+ }
+ else
+ {
+ ptr_rx_cb->cnt.channel[queue].deque_fail++;
}
-
- /* Must free kernel sw_gpd */
- _hal_tau_pkt_freeRxGpdList(unit, ptr_sw_first_gpd_knl, TRUE);
}
else
{
- ptr_rx_cb->cnt.channel[queue].deque_fail++;
+ /* it means that all queue's are flush -> rx stop flow */
+ rc = NPS_E_OTHERS;
}
}
- else
- {
- /* It may happen at last gpd, return error and do not invoke callback. */
- rc = NPS_E_OTHERS;
- }
return (rc);
}
@@ -2547,6 +2775,26 @@ _hal_tau_pkt_suspendAllIntf(
return (NPS_E_OK);
}
+static NPS_ERROR_NO_T
+_hal_tau_pkt_stopAllIntf(
+ const UI32_T unit)
+{
+ struct net_device *ptr_net_dev = NULL;
+ UI32_T port;
+
+ /* Unregister net devices by id */
+ for (port = 0; port < HAL_TAU_PKT_MAX_PORT_NUM; port++)
+ {
+ ptr_net_dev = HAL_TAU_PKT_GET_PORT_NETDEV(port);
+ if (NULL != ptr_net_dev)
+ {
+ netif_tx_disable(ptr_net_dev);
+ }
+ }
+
+ return (NPS_E_OK);
+}
+
/* FUNCTION NAME: hal_tau_pkt_sendGpd
* PURPOSE:
* To perform the packet transmission form CPU to the switch.
@@ -2572,85 +2820,94 @@ hal_tau_pkt_sendGpd(
HAL_TAU_PKT_TX_PDMA_T *ptr_tx_pdma = HAL_TAU_PKT_GET_TX_PDMA_PTR(unit, channel);
volatile HAL_TAU_PKT_TX_GPD_T *ptr_tx_gpd = NULL;
HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_first_gpd = ptr_sw_gpd;
-
UI32_T used_idx = 0;
UI32_T used_gpd_num = ptr_sw_gpd->gpd_num;
NPS_IRQ_FLAGS_T irq_flags;
+ HAL_TAU_PKT_DRV_CB_T *ptr_cb = HAL_TAU_PKT_GET_DRV_CB_PTR(unit);
- osal_takeIsrLock(&ptr_tx_pdma->ring_lock, &irq_flags);
-
- /* If not PDMA error */
- if (FALSE == ptr_tx_pdma->err_flag)
+ if (0 != (ptr_cb->init_flag & HAL_TAU_PKT_INIT_TASK))
{
- /* Make Sure GPD is enough */
- if (ptr_tx_pdma->free_gpd_num >= used_gpd_num)
+ osal_takeIsrLock(&ptr_tx_pdma->ring_lock, &irq_flags);
+
+ /* If not PDMA error */
+ if (FALSE == ptr_tx_pdma->err_flag)
{
- used_idx = ptr_tx_pdma->used_idx;
- while (NULL != ptr_sw_gpd)
+ /* Make Sure GPD is enough */
+ if (ptr_tx_pdma->free_gpd_num >= used_gpd_num)
{
- ptr_tx_gpd = HAL_TAU_PKT_GET_TX_GPD_PTR(unit, channel, used_idx);
- osal_dma_invalidateCache((void *)ptr_tx_gpd, sizeof(HAL_TAU_PKT_TX_GPD_T));
-
- if (HAL_TAU_PKT_HWO_HW_OWN == ptr_tx_gpd->hwo)
+ used_idx = ptr_tx_pdma->used_idx;
+ while (NULL != ptr_sw_gpd)
{
- HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX),
- "u=%u, txch=%u, free gpd idx out-of-sync\n",
- unit, channel);
- rc = NPS_E_TABLE_FULL;
- break;
- }
+ ptr_tx_gpd = HAL_TAU_PKT_GET_TX_GPD_PTR(unit, channel, used_idx);
+ osal_dma_invalidateCache((void *)ptr_tx_gpd, sizeof(HAL_TAU_PKT_TX_GPD_T));
- /* Fill in HW-GPD Ring */
- osal_memcpy((void *)ptr_tx_gpd, &ptr_sw_gpd->tx_gpd, sizeof(HAL_TAU_PKT_TX_GPD_T));
- osal_dma_flushCache((void *)ptr_tx_gpd, sizeof(HAL_TAU_PKT_TX_GPD_T));
+ if (HAL_TAU_PKT_HWO_HW_OWN == ptr_tx_gpd->hwo)
+ {
+ HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX),
+ "u=%u, txch=%u, free gpd idx out-of-sync\n",
+ unit, channel);
+ rc = NPS_E_TABLE_FULL;
+ break;
+ }
- /* next */
- used_idx++;
- used_idx %= ptr_tx_pdma->gpd_num;
- ptr_sw_gpd = ptr_sw_gpd->ptr_next;
- }
+ /* Fill in HW-GPD Ring */
+ osal_memcpy((void *)ptr_tx_gpd, &ptr_sw_gpd->tx_gpd, sizeof(HAL_TAU_PKT_TX_GPD_T));
+ osal_dma_flushCache((void *)ptr_tx_gpd, sizeof(HAL_TAU_PKT_TX_GPD_T));
- if (HAL_TAU_PKT_TX_WAIT_ASYNC == ptr_tx_cb->wait_mode)
- {
- /* Fill 1st GPD in SW-GPD Ring */
- ptr_tx_pdma->pptr_sw_gpd_ring[ptr_tx_pdma->used_idx] = ptr_sw_first_gpd;
- }
+ /* next */
+ used_idx++;
+ used_idx %= ptr_tx_pdma->gpd_num;
+ ptr_sw_gpd = ptr_sw_gpd->ptr_next;
+ }
- /* update Tx PDMA */
- ptr_tx_pdma->used_idx = used_idx;
- ptr_tx_pdma->used_gpd_num += used_gpd_num;
- ptr_tx_pdma->free_gpd_num -= used_gpd_num;
+ if (HAL_TAU_PKT_TX_WAIT_ASYNC == ptr_tx_cb->wait_mode)
+ {
+ /* Fill 1st GPD in SW-GPD Ring */
+ ptr_tx_pdma->pptr_sw_gpd_ring[ptr_tx_pdma->used_idx] = ptr_sw_first_gpd;
+ }
+
+ /* update Tx PDMA */
+ ptr_tx_pdma->used_idx = used_idx;
+ ptr_tx_pdma->used_gpd_num += used_gpd_num;
+ ptr_tx_pdma->free_gpd_num -= used_gpd_num;
- _hal_tau_pkt_resumeTxChannelReg(unit, channel, used_gpd_num);
- ptr_tx_cb->cnt.channel[channel].send_ok++;
+ _hal_tau_pkt_resumeTxChannelReg(unit, channel, used_gpd_num);
+ ptr_tx_cb->cnt.channel[channel].send_ok++;
- _hal_tau_pkt_waitTxDone(unit, channel, ptr_sw_first_gpd);
+ _hal_tau_pkt_waitTxDone(unit, channel, ptr_sw_first_gpd);
- /* reserve 1 packet buffer for each port in case that the suspension is too late */
-#define HAL_TAU_PKT_KNL_TX_RING_AVBL_GPD_LOW (HAL_TAU_PORT_NUM)
- if (ptr_tx_pdma->free_gpd_num < HAL_TAU_PKT_KNL_TX_RING_AVBL_GPD_LOW)
+ /* reserve 1 packet buffer for each port in case that the suspension is too late */
+#define HAL_TAU_PKT_KNL_TX_RING_AVBL_GPD_LOW (HAL_PORT_NUM)
+ if (ptr_tx_pdma->free_gpd_num < HAL_TAU_PKT_KNL_TX_RING_AVBL_GPD_LOW)
+ {
+ HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_TX,
+ "u=%u, txch=%u, tx avbl gpd < %d, suspend all netdev\n",
+ unit, channel, HAL_TAU_PKT_KNL_TX_RING_AVBL_GPD_LOW);
+ _hal_tau_pkt_suspendAllIntf(unit);
+ }
+ }
+ else
{
- HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_TX,
- "u=%u, txch=%u, tx avbl gpd < %d, suspend all netdev\n",
- unit, channel, HAL_TAU_PKT_KNL_TX_RING_AVBL_GPD_LOW);
- _hal_tau_pkt_suspendAllIntf(unit);
+ rc = NPS_E_TABLE_FULL;
}
}
else
{
- rc = NPS_E_TABLE_FULL;
+ HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX),
+ "u=%u, txch=%u, pdma hw err\n",
+ unit, channel);
+ rc = NPS_E_OTHERS;
}
+
+ osal_giveIsrLock(&ptr_tx_pdma->ring_lock, &irq_flags);
}
else
{
- HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX),
- "u=%u, txch=%u, pdma hw err\n",
- unit, channel);
+ HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR,
+ "Tx failed, task already deinit\n");
rc = NPS_E_OTHERS;
}
- osal_giveIsrLock(&ptr_tx_pdma->ring_lock, &irq_flags);
-
return (rc);
}
@@ -2662,6 +2919,7 @@ _hal_tau_pkt_rxStop(
{
NPS_ERROR_NO_T rc = NPS_E_OK;
HAL_TAU_PKT_RX_CHANNEL_T channel = 0;
+ UI32_T idx;
HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit);
HAL_TAU_PKT_DRV_CB_T *ptr_cb = HAL_TAU_PKT_GET_DRV_CB_PTR(unit);
HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma = NULL;
@@ -2695,6 +2953,14 @@ _hal_tau_pkt_rxStop(
osal_giveSemaphore(&ptr_rx_pdma->sema);
}
+ /* flush packets in all queues since Rx task may be blocked in user space
+ * in this case it won't do ioctl to kernel to handle remaining packets
+ */
+ for (idx = 0; idx < HAL_TAU_PKT_RX_QUEUE_NUM; idx++)
+ {
+ _hal_tau_pkt_flushRxQueue(unit, &ptr_rx_cb->sw_queue[idx]);
+ }
+
/* Return user thread */
ptr_rx_cb->running = FALSE;
ptr_cb->init_flag &= (~HAL_TAU_PKT_INIT_RX_START);
@@ -2848,6 +3114,12 @@ hal_tau_pkt_deinitTask(
HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit);
UI32_T channel = 0;
+ /* to prevent net intf from Tx packet */
+ ptr_tx_cb->net_tx_allowed = FALSE;
+
+ /* In case that some undestroyed net intf keep Tx after task deinit */
+ _hal_tau_pkt_stopAllIntf(unit);
+
if (0 == (ptr_cb->init_flag & HAL_TAU_PKT_INIT_TASK))
{
HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_RX | HAL_TAU_PKT_DBG_ERR),
@@ -2926,13 +3198,10 @@ _hal_tau_pkt_deinitTxPdma(
{
HAL_TAU_PKT_TX_CB_T *ptr_tx_cb = HAL_TAU_PKT_GET_TX_CB_PTR(unit);
HAL_TAU_PKT_TX_PDMA_T *ptr_tx_pdma = HAL_TAU_PKT_GET_TX_PDMA_PTR(unit, channel);
- NPS_IRQ_FLAGS_T irg_flags;
_hal_tau_pkt_stopTxChannelReg(unit, channel);
/* Free DMA and flush queue */
- osal_takeIsrLock(&ptr_tx_pdma->ring_lock, &irg_flags);
-
osal_dma_free(ptr_tx_pdma->ptr_gpd_start_addr);
if (HAL_TAU_PKT_TX_WAIT_ASYNC == ptr_tx_cb->wait_mode)
@@ -2945,8 +3214,6 @@ _hal_tau_pkt_deinitTxPdma(
osal_destroySemaphore(&ptr_tx_pdma->sync_intr_sema);
}
- osal_giveIsrLock(&ptr_tx_pdma->ring_lock, &irg_flags);
-
osal_destroyIsrLock(&ptr_tx_pdma->ring_lock);
return (NPS_E_OK);
@@ -3919,6 +4186,7 @@ _hal_tau_pkt_handleRxDoneTask(
ptr_sw_gpd->ptr_next = NULL;
ptr_sw_first_gpd->rx_complete = FALSE;
_hal_tau_pkt_rxEnQueue(unit, channel, ptr_sw_first_gpd);
+ ptr_sw_first_gpd = NULL;
}
/* do error recover */
@@ -3956,7 +4224,7 @@ _hal_tau_pkt_handleRxDoneTask(
{
ptr_rx_cb->cnt.no_memory++;
HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_RX | HAL_TAU_PKT_DBG_ERR),
- "u=%u, rxch=%u, alloc 1st sw gpd failed, size=%d\n",
+ "u=%u, rxch=%u, alloc 1st sw gpd failed, size=%zu\n",
unit, channel, sizeof(HAL_TAU_PKT_RX_SW_GPD_T));
break;
}
@@ -3973,7 +4241,7 @@ _hal_tau_pkt_handleRxDoneTask(
{
ptr_rx_cb->cnt.no_memory++;
HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_RX | HAL_TAU_PKT_DBG_ERR),
- "u=%u, rxch=%u, alloc mid sw gpd failed, size=%d\n",
+ "u=%u, rxch=%u, alloc mid sw gpd failed, size=%zu\n",
unit, channel, sizeof(HAL_TAU_PKT_RX_SW_GPD_T));
break;
}
@@ -4003,6 +4271,7 @@ _hal_tau_pkt_handleRxDoneTask(
ptr_sw_gpd->ptr_next = NULL;
ptr_sw_first_gpd->rx_complete = TRUE;
_hal_tau_pkt_rxEnQueue(unit, channel, ptr_sw_first_gpd);
+ ptr_sw_first_gpd = NULL;
/* To rebuild the SW GPD link list */
first = TRUE;
@@ -4085,8 +4354,8 @@ hal_tau_pkt_initTask(
}
/* Init handleErrorTask */
- rc = osal_createThread("ERROR", HAL_TAU_PKT_ERROR_ISR_STACK_SIZE,
- HAL_TAU_PKT_ERROR_ISR_THREAD_PRI, _hal_tau_pkt_handleErrorTask,
+ rc = osal_createThread("ERROR", HAL_DFLT_CFG_PKT_ERROR_ISR_THREAD_STACK,
+ HAL_DFLT_CFG_PKT_ERROR_ISR_THREAD_PRI, _hal_tau_pkt_handleErrorTask,
(void *)((NPS_HUGE_T)unit), &ptr_cb->err_task_id);
/* Init handleTxDoneTask */
@@ -4095,8 +4364,8 @@ hal_tau_pkt_initTask(
ptr_tx_cb->isr_task_cookie[channel].unit = unit;
ptr_tx_cb->isr_task_cookie[channel].channel = channel;
- rc = osal_createThread("TX_ISR", HAL_TAU_PKT_TX_ISR_STACK_SIZE,
- HAL_TAU_PKT_TX_ISR_THREAD_PRI, _hal_tau_pkt_handleTxDoneTask,
+ rc = osal_createThread("TX_ISR", HAL_DFLT_CFG_PKT_TX_ISR_THREAD_STACK,
+ HAL_DFLT_CFG_PKT_TX_ISR_THREAD_PRI, _hal_tau_pkt_handleTxDoneTask,
(void *)&ptr_tx_cb->isr_task_cookie[channel],
&ptr_tx_cb->isr_task_id[channel]);
}
@@ -4107,8 +4376,8 @@ hal_tau_pkt_initTask(
ptr_rx_cb->isr_task_cookie[channel].unit = unit;
ptr_rx_cb->isr_task_cookie[channel].channel = channel;
- rc = osal_createThread("RX_ISR", HAL_TAU_PKT_RX_ISR_STACK_SIZE,
- HAL_TAU_PKT_RX_ISR_THREAD_PRI, _hal_tau_pkt_handleRxDoneTask,
+ rc = osal_createThread("RX_ISR", HAL_DFLT_CFG_PKT_RX_ISR_THREAD_STACK,
+ HAL_DFLT_CFG_PKT_RX_ISR_THREAD_PRI, _hal_tau_pkt_handleRxDoneTask,
(void *)&ptr_rx_cb->isr_task_cookie[channel],
&ptr_rx_cb->isr_task_id[channel]);
}
@@ -4124,6 +4393,13 @@ hal_tau_pkt_initTask(
HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON,
"u=%u, pkt task init done, init flag=0x%x\n", unit, ptr_cb->init_flag);
+ /* For some specail case in warmboot, the netifs are not destroyed during sdk deinit
+ * but stopped, here we need to resume them with the original carrier status
+ */
+ _hal_tau_pkt_resumeAllIntf(unit);
+
+ ptr_tx_cb->net_tx_allowed = TRUE;
+
return (rc);
}
@@ -4165,8 +4441,8 @@ _hal_tau_pkt_initTxPdma(
ptr_tx_pdma->used_idx = 0;
ptr_tx_pdma->free_idx = 0;
ptr_tx_pdma->used_gpd_num = 0;
- ptr_tx_pdma->free_gpd_num = HAL_TAU_PKT_PDMA_TX_GPD_NUM;
- ptr_tx_pdma->gpd_num = HAL_TAU_PKT_PDMA_TX_GPD_NUM;
+ ptr_tx_pdma->free_gpd_num = HAL_DFLT_CFG_PKT_TX_GPD_NUM;
+ ptr_tx_pdma->gpd_num = HAL_DFLT_CFG_PKT_TX_GPD_NUM;
/* Prepare the HW-GPD ring */
ptr_tx_pdma->ptr_gpd_start_addr = (HAL_TAU_PKT_TX_GPD_T *)osal_dma_alloc(
@@ -4263,7 +4539,7 @@ _hal_tau_pkt_initRxPdma(
/* Reset Rx PDMA */
osal_takeSemaphore(&ptr_rx_pdma->sema, NPS_SEMAPHORE_WAIT_FOREVER);
ptr_rx_pdma->cur_idx = 0;
- ptr_rx_pdma->gpd_num = HAL_TAU_PKT_PDMA_RX_GPD_NUM;
+ ptr_rx_pdma->gpd_num = HAL_DFLT_CFG_PKT_RX_GPD_NUM;
/* Prepare the HW-GPD ring */
ptr_rx_pdma->ptr_gpd_start_addr = (HAL_TAU_PKT_RX_GPD_T *)osal_dma_alloc(
@@ -4374,7 +4650,7 @@ _hal_tau_pkt_initPktTxCb(
osal_createEvent("TX_SYNC", &ptr_tx_cb->sync_sema);
/* Initialize Tx GPD-queue (of first SW-GPD) from handleTxDoneTask to txTask */
- ptr_tx_cb->sw_queue.len = HAL_TAU_PKT_TX_QUEUE_LEN;
+ ptr_tx_cb->sw_queue.len = HAL_DFLT_CFG_PKT_TX_QUEUE_LEN;
ptr_tx_cb->sw_queue.weight = 0;
osal_createSemaphore("TX_QUE", NPS_SEMAPHORE_BINARY, &ptr_tx_cb->sw_queue.sema);
@@ -4422,7 +4698,7 @@ _hal_tau_pkt_initPktRxCb(
osal_memset(ptr_rx_cb, 0x0, sizeof(HAL_TAU_PKT_RX_CB_T));
- ptr_rx_cb->sched_mode = HAL_TAU_PKT_RX_SCHED_MODE;
+ ptr_rx_cb->sched_mode = HAL_DFLT_CFG_PKT_RX_SCHED_MODE;
/* Sync semaphore to signal rxTask */
osal_createEvent("RX_SYNC", &ptr_rx_cb->sync_sema);
@@ -4430,8 +4706,8 @@ _hal_tau_pkt_initPktRxCb(
/* Initialize Rx GPD-queue (of first SW-GPD) from handleRxDoneTask to rxTask */
for (queue = 0; ((queue < HAL_TAU_PKT_RX_QUEUE_NUM) && (NPS_E_OK == rc)); queue++)
{
- ptr_rx_cb->sw_queue[queue].len = HAL_TAU_PKT_RX_QUEUE_LEN;
- ptr_rx_cb->sw_queue[queue].weight = HAL_TAU_PKT_RX_QUEUE_WEIGHT;
+ ptr_rx_cb->sw_queue[queue].len = HAL_DFLT_CFG_PKT_RX_QUEUE_LEN;
+ ptr_rx_cb->sw_queue[queue].weight = HAL_DFLT_CFG_PKT_RX_QUEUE_WEIGHT;
osal_createSemaphore("RX_QUE", NPS_SEMAPHORE_BINARY, &ptr_rx_cb->sw_queue[queue].sema);
osal_que_create(&ptr_rx_cb->sw_queue[queue].que_id, ptr_rx_cb->sw_queue[queue].len);
@@ -4530,12 +4806,12 @@ _hal_tau_pkt_resetIosCreditCfg(
osal_mdc_readPciReg(unit, HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_CREDIT_CFG),
&credit_cfg, sizeof(credit_cfg));
- credit_cfg |= (0x1 << HAL_TAU_PKT_PDMA_CREDIT_CFG_RESET_OFFSET);
+ credit_cfg |= (0x1UL << HAL_TAU_PKT_PDMA_CREDIT_CFG_RESET_OFFSET);
osal_mdc_writePciReg(unit, HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_CREDIT_CFG),
&credit_cfg, sizeof(UI32_T));
- credit_cfg &= ~(0x1 << HAL_TAU_PKT_PDMA_CREDIT_CFG_RESET_OFFSET);
+ credit_cfg &= ~(0x1UL << HAL_TAU_PKT_PDMA_CREDIT_CFG_RESET_OFFSET);
osal_mdc_writePciReg(unit, HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_CREDIT_CFG),
&credit_cfg, sizeof(UI32_T));
@@ -4544,27 +4820,6 @@ _hal_tau_pkt_resetIosCreditCfg(
return (NPS_E_OK);
}
-static NPS_ERROR_NO_T
-_hal_tau_pkt_stopAllIntf(
- const UI32_T unit)
-{
- struct net_device *ptr_net_dev = NULL;
- UI32_T port;
-
- /* Unregister net devices by id */
- for (port = 0; port < HAL_TAU_PKT_MAX_PORT_NUM; port++)
- {
- ptr_net_dev = HAL_TAU_PKT_GET_PORT_NETDEV(port);
- if (NULL != ptr_net_dev)
- {
- netif_carrier_off(ptr_net_dev);
- netif_stop_queue(ptr_net_dev);
- }
- }
-
- return (NPS_E_OK);
-}
-
static NPS_ERROR_NO_T
_hal_tau_pkt_addProfToList(
HAL_TAU_PKT_NETIF_PROFILE_T *ptr_new_profile,
@@ -4668,8 +4923,8 @@ _hal_tau_pkt_addProfToAllIntf(
for (port = 0; port < HAL_TAU_PKT_MAX_PORT_NUM; port++)
{
ptr_port_db = HAL_TAU_PKT_GET_PORT_DB(port);
- /* Shall we check if the interface is ever created in the port?? */
- //if (NULL != ptr_port_db->ptr_net_dev)
+ /* Shall we check if the interface is ever created on the port?? */
+ /* if (NULL != ptr_port_db->ptr_net_dev) */
if (1)
{
_hal_tau_pkt_addProfToList(ptr_new_profile, &ptr_port_db->ptr_profile_list);
@@ -4759,8 +5014,8 @@ _hal_tau_pkt_delProfFromAllIntfById(
for (port = 0; port < HAL_TAU_PKT_MAX_PORT_NUM; port++)
{
ptr_port_db = HAL_TAU_PKT_GET_PORT_DB(port);
- /* Shall we check if the interface is ever created in the port?? */
- //if (NULL != ptr_port_db->ptr_net_dev)
+ /* Shall we check if the interface is ever created on the port?? */
+ /* if (NULL != ptr_port_db->ptr_net_dev) */
if (1)
{
_hal_tau_pkt_delProfFromListById(id, &ptr_port_db->ptr_profile_list);
@@ -4824,7 +5079,7 @@ _hal_tau_pkt_destroyAllIntf(
ptr_port_db->meta.port,
ptr_port_db->meta.port);
- netif_stop_queue(ptr_port_db->ptr_net_dev);
+ netif_tx_disable(ptr_port_db->ptr_net_dev);
unregister_netdev(ptr_port_db->ptr_net_dev);
free_netdev(ptr_port_db->ptr_net_dev);
@@ -5072,7 +5327,7 @@ hal_tau_pkt_prepareGpd(
*/
ptr_sw_gpd->tx_gpd.itmh_eth.dst_idx = port;
- /* [Taurus] we should set all-1 for the following fields to skip some tm-logic */
+ /* [NP8360] we should set all-1 for the following fields to skip some tm-logic */
/* TM header */
ptr_sw_gpd->tx_gpd.itmh_eth.src_idx = 0x7fff;
@@ -5083,8 +5338,8 @@ hal_tau_pkt_prepareGpd(
ptr_sw_gpd->tx_gpd.itmh_eth.nvo3_src_supp_tag_w1 = 0xf;
/* PP header */
- ptr_sw_gpd->tx_gpd.pph_l2.nvo3_encap_idx = HAL_TAU_INVALID_NVO3_ENCAP_IDX;
- ptr_sw_gpd->tx_gpd.pph_l2.nvo3_adj_idx = HAL_TAU_INVALID_NVO3_ADJ_IDX;
+ ptr_sw_gpd->tx_gpd.pph_l2.nvo3_encap_idx = HAL_INVALID_NVO3_ENCAP_IDX;
+ ptr_sw_gpd->tx_gpd.pph_l2.nvo3_adj_idx = HAL_INVALID_NVO3_ADJ_IDX;
return (NPS_E_OK);
}
@@ -5157,6 +5412,7 @@ _hal_tau_pkt_net_dev_tx(
struct net_device *ptr_net_dev)
{
struct net_device_priv *ptr_priv = netdev_priv(ptr_net_dev);
+ HAL_TAU_PKT_TX_CB_T *ptr_tx_cb;
/* chip meta */
unsigned int unit;
unsigned int channel = 0;
@@ -5180,6 +5436,17 @@ _hal_tau_pkt_net_dev_tx(
unit = ptr_priv->unit;
+ ptr_tx_cb = HAL_TAU_PKT_GET_TX_CB_PTR(unit);
+ /* for warm de-init procedure, if any net intf not destroyed, it is possible
+ * that kernel still has packets to send causing segmentation fault
+ */
+ if (FALSE == ptr_tx_cb->net_tx_allowed) {
+ HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR, "net tx during sdk de-init\n");
+ ptr_priv->stats.tx_dropped++;
+ osal_skb_free(ptr_skb);
+ return NETDEV_TX_OK;
+ }
+
/* pad to 60-bytes if skb_len < 60, see: eth_skb_pad(skb) */
if (ptr_skb->len < ETH_ZLEN)
{
@@ -5245,8 +5512,6 @@ _hal_tau_pkt_net_dev_tx(
osal_skb_unmapDma(phy_addr, ptr_skb->len, DMA_TO_DEVICE);
osal_skb_free(ptr_skb);
osal_free(ptr_sw_gpd);
-
- return NETDEV_TX_OK;
}
}
}
@@ -5374,34 +5639,6 @@ _hal_tau_pkt_setup(
memset(&ptr_priv->stats, 0, sizeof(struct net_device_stats));
}
-static void
-_hal_tau_pkt_lockRxChannelAll(
- const UI32_T unit)
-{
- UI32_T rch;
- HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma;
-
- for (rch = 0; rch < HAL_TAU_PKT_RX_CHANNEL_LAST; rch++)
- {
- ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, rch);
- osal_takeSemaphore(&ptr_rx_pdma->sema, NPS_SEMAPHORE_WAIT_FOREVER);
- }
-}
-
-static void
-_hal_tau_pkt_unlockRxChannelAll(
- const UI32_T unit)
-{
- UI32_T rch;
- HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma;
-
- for (rch = 0; rch < HAL_TAU_PKT_RX_CHANNEL_LAST; rch++)
- {
- ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, rch);
- osal_giveSemaphore(&ptr_rx_pdma->sema);
- }
-}
-
static NPS_ERROR_NO_T
_hal_tau_pkt_createIntf(
const UI32_T unit,
@@ -5435,7 +5672,7 @@ _hal_tau_pkt_createIntf(
#if defined(HAL_TAU_PKT_FORCR_REMOVE_DUPLICATE_NETDEV)
ptr_net_dev->operstate = IF_OPER_DOWN;
netif_carrier_off(ptr_net_dev);
- netif_stop_queue(ptr_net_dev);
+ netif_tx_disable(ptr_net_dev);
unregister_netdev(ptr_net_dev);
free_netdev(ptr_net_dev);
#endif
@@ -5466,6 +5703,8 @@ _hal_tau_pkt_createIntf(
register_netdev(ptr_net_dev);
+ netif_carrier_off(ptr_net_dev);
+
net_intf.id = net_intf.port; /* Currently, id is 1-to-1 mapped to port */
osal_memcpy(&ptr_port_db->meta, &net_intf, sizeof(HAL_TAU_PKT_NETIF_INTF_T));
@@ -5518,10 +5757,11 @@ _hal_tau_pkt_destroyIntf(
"u=%u, find intf %s (id=%d) on phy port=%d, destroy done\n",
unit,
ptr_port_db->meta.name,
+ ptr_port_db->meta.id,
ptr_port_db->meta.port);
netif_carrier_off(ptr_port_db->ptr_net_dev);
- netif_stop_queue(ptr_port_db->ptr_net_dev);
+ netif_tx_disable(ptr_port_db->ptr_net_dev);
unregister_netdev(ptr_port_db->ptr_net_dev);
free_netdev(ptr_port_db->ptr_net_dev);
@@ -5553,7 +5793,7 @@ _hal_tau_pkt_traverseProfList(
ptr_curr_node = ptr_prof_list;
- HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_INTF, "intf id=%d, prof list=\n", intf_id);
+ HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_INTF, "intf id=%d, prof list=", intf_id);
while(NULL != ptr_curr_node)
{
HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_INTF, "%s (%d) => ",
@@ -6043,6 +6283,24 @@ _hal_tau_pkt_dev_ioctl(
ret = hal_tau_pkt_setPortAttr(unit, (HAL_TAU_PKT_IOCTL_PORT_COOKIE_T *)arg);
break;
+#if defined(NETIF_EN_NETLINK)
+ case HAL_TAU_PKT_IOCTL_TYPE_NL_SET_INTF_PROPERTY:
+ ret = _hal_tau_pkt_setIntfProperty(unit, (HAL_TAU_PKT_NL_IOCTL_COOKIE_T *)arg);
+ break;
+ case HAL_TAU_PKT_IOCTL_TYPE_NL_GET_INTF_PROPERTY:
+ ret = _hal_tau_pkt_getIntfProperty(unit, (HAL_TAU_PKT_NL_IOCTL_COOKIE_T *)arg);
+ break;
+ case HAL_TAU_PKT_IOCTL_TYPE_NL_CREATE_NETLINK:
+ ret = _hal_tau_pkt_createNetlink(unit, (HAL_TAU_PKT_NL_IOCTL_COOKIE_T *)arg);
+ break;
+ case HAL_TAU_PKT_IOCTL_TYPE_NL_DESTROY_NETLINK:
+ ret = _hal_tau_pkt_destroyNetlink(unit, (HAL_TAU_PKT_NL_IOCTL_COOKIE_T *)arg);
+ break;
+ case HAL_TAU_PKT_IOCTL_TYPE_NL_GET_NETLINK:
+ ret = _hal_tau_pkt_getNetlink(unit, (HAL_TAU_PKT_NL_IOCTL_COOKIE_T *)arg);
+ break;
+#endif
+
default:
ret = -1;
break;
@@ -6102,6 +6360,10 @@ _hal_tau_pkt_init(void)
osal_memset(_hal_tau_pkt_drv_cb, 0x0,
NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM*sizeof(HAL_TAU_PKT_DRV_CB_T));
+#if defined(NETIF_EN_NETLINK)
+ netif_nl_init();
+#endif
+
return (0);
}
@@ -6110,16 +6372,16 @@ _hal_tau_pkt_exit(void)
{
UI32_T unit = 0;
- /* 1st. Stop Rx HW DMA and free all the DMA buffer hooked on the ring */
+ /* 1st. Stop all netdev (if any) to prevent kernel from Tx new packets */
+ _hal_tau_pkt_stopAllIntf(unit);
+
+ /* 2nd. Stop Rx HW DMA and free all the DMA buffer hooked on the ring */
_hal_tau_pkt_rxStop(unit);
- /* 2nd. Need to wait Rx done task process all the availavle packets on GPD ring */
+ /* 3rd. Need to wait Rx done task process all the availavle packets on GPD ring */
#define HAL_TAU_PKT_MODULE_EXIT_HOLD_TIME_US (1000000)
osal_sleepThread(HAL_TAU_PKT_MODULE_EXIT_HOLD_TIME_US);
- /* 3rd. Stop all netdev (if any) to prevent kernel from Tx new packets */
- _hal_tau_pkt_stopAllIntf(unit);
-
/* 4th. Stop all the internal tasks (if any) */
hal_tau_pkt_deinitTask(unit);
@@ -6139,9 +6401,9 @@ _hal_tau_pkt_exit(void)
module_init(_hal_tau_pkt_init);
module_exit(_hal_tau_pkt_exit);
-module_param(dbg_flag, uint, S_IRUGO);
-MODULE_PARM_DESC(dbg_flag, "bit0:Error, bit1:Tx, bit2:Rx, bit3:Intf, bit4:Profile");
+module_param(ext_dbg_flag, uint, S_IRUGO);
+MODULE_PARM_DESC(ext_dbg_flag, "bit0:Error, bit1:Tx, bit2:Rx, bit3:Intf, bit4:Profile");
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Nephos");
+MODULE_AUTHOR("MediaTek");
MODULE_DESCRIPTION("NETIF Kernel Module");
diff --git a/platform/nephos/nephos-modules/modules/src/inc/aml.h b/platform/nephos/nephos-modules/modules/src/inc/aml.h
index 658aa6e56f46..682eaa5ea318 100755
--- a/platform/nephos/nephos-modules/modules/src/inc/aml.h
+++ b/platform/nephos/nephos-modules/modules/src/inc/aml.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/platform/nephos/nephos-modules/modules/src/inc/hal_dev.h b/platform/nephos/nephos-modules/modules/src/inc/hal_dev.h
index edd582adc197..e8d491358c77 100755
--- a/platform/nephos/nephos-modules/modules/src/inc/hal_dev.h
+++ b/platform/nephos/nephos-modules/modules/src/inc/hal_dev.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/platform/nephos/nephos-modules/modules/src/inc/hal_tau_pkt_knl.h b/platform/nephos/nephos-modules/modules/src/inc/hal_tau_pkt_knl.h
index 96a8cf6441f0..3605323a5955 100755
--- a/platform/nephos/nephos-modules/modules/src/inc/hal_tau_pkt_knl.h
+++ b/platform/nephos/nephos-modules/modules/src/inc/hal_tau_pkt_knl.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -104,15 +104,15 @@ typedef enum
/* hal_tau_const.h */
-#define HAL_TAU_PORT_NUM (128)
-#define HAL_TAU_EXCPT_CPU_NUM (256)
-#define HAL_TAU_INVALID_NVO3_ENCAP_IDX (0x3FFF)
-#define HAL_TAU_INVALID_NVO3_ADJ_IDX (0xFF)
-#define HAL_TAU_EXCPT_CPU_BASE_ID (28 * 1024)
-#define HAL_TAU_EXCPT_CPU_NON_L3_MIN (0)
-#define HAL_TAU_EXCPT_CPU_NON_L3_MAX (HAL_TAU_EXCPT_CPU_NON_L3_MIN + HAL_TAU_EXCPT_CPU_NUM - 1)
-#define HAL_TAU_EXCPT_CPU_L3_MIN (HAL_TAU_EXCPT_CPU_NON_L3_MIN + HAL_TAU_EXCPT_CPU_NUM)
-#define HAL_TAU_EXCPT_CPU_L3_MAX (HAL_TAU_EXCPT_CPU_L3_MIN + HAL_TAU_EXCPT_CPU_NUM - 1)
+#define HAL_PORT_NUM (128)
+#define HAL_EXCPT_CPU_NUM (256)
+#define HAL_INVALID_NVO3_ENCAP_IDX (0x3FFF)
+#define HAL_INVALID_NVO3_ADJ_IDX (0xFF)
+#define HAL_EXCPT_CPU_BASE_ID (28 * 1024)
+#define HAL_EXCPT_CPU_NON_L3_MIN (0)
+#define HAL_EXCPT_CPU_NON_L3_MAX (HAL_EXCPT_CPU_NON_L3_MIN + HAL_EXCPT_CPU_NUM - 1)
+#define HAL_EXCPT_CPU_L3_MIN (HAL_EXCPT_CPU_NON_L3_MIN + HAL_EXCPT_CPU_NUM)
+#define HAL_EXCPT_CPU_L3_MAX (HAL_EXCPT_CPU_L3_MIN + HAL_EXCPT_CPU_NUM - 1)
/* hal_tau_pkt_rsrc.h */
#define HAL_TAU_PKT_IPP_EXCPT_LAST (256)
@@ -238,7 +238,7 @@ typedef struct
HAL_TAU_PKT_IPP_COPY2CPU_BITMAP_T ipp_copy2cpu_bitmap;
HAL_TAU_PKT_EPP_COPY2CPU_BITMAP_T epp_copy2cpu_bitmap;
-} HAL_TAU_PKT_RX_REASON_BITMAP_T;
+} HAL_PKT_RX_REASON_BITMAP_T;
/* hal_tau_pkt.h */
@@ -246,23 +246,23 @@ typedef struct
/* NAMING DECLARATIONS
*/
/* PKT related configurable parameters */
-#define HAL_TAU_PKT_RX_FREE_STACK_SIZE (64 * 1024)
-#define HAL_TAU_PKT_RX_FREE_THREAD_PRI (80)
+#define HAL_DFLT_CFG_PKT_RX_FREE_STACK_SIZE (64 * 1024)
+#define HAL_DFLT_CFG_PKT_RX_FREE_THREAD_PRI (80)
-#define HAL_TAU_PKT_RX_ISR_STACK_SIZE (64 * 1024)
-#define HAL_TAU_PKT_RX_ISR_THREAD_PRI (80)
+#define HAL_DFLT_CFG_PKT_RX_ISR_THREAD_STACK (64 * 1024)
+#define HAL_DFLT_CFG_PKT_RX_ISR_THREAD_PRI (80)
-#define HAL_TAU_PKT_TX_FREE_STACK_SIZE (64 * 1024)
-#define HAL_TAU_PKT_TX_FREE_THREAD_PRI (80)
+#define HAL_DFLT_CFG_PKT_TX_FREE_STACK_SIZE (64 * 1024)
+#define HAL_DFLT_CFG_PKT_TX_FREE_THREAD_PRI (80)
-#define HAL_TAU_PKT_TX_ISR_STACK_SIZE (64 * 1024)
-#define HAL_TAU_PKT_TX_ISR_THREAD_PRI (80)
+#define HAL_DFLT_CFG_PKT_TX_ISR_THREAD_STACK (64 * 1024)
+#define HAL_DFLT_CFG_PKT_TX_ISR_THREAD_PRI (80)
-#define HAL_TAU_PKT_TX_NET_STACK_SIZE (64 * 1024)
-#define HAL_TAU_PKT_TX_NET_THREAD_PRI (80)
+#define HAL_DFLT_CFG_PKT_TX_NET_STACK_SIZE (64 * 1024)
+#define HAL_DFLT_CFG_PKT_TX_NET_THREAD_PRI (80)
-#define HAL_TAU_PKT_ERROR_ISR_STACK_SIZE (64 * 1024)
-#define HAL_TAU_PKT_ERROR_ISR_THREAD_PRI (80)
+#define HAL_DFLT_CFG_PKT_ERROR_ISR_THREAD_STACK (64 * 1024)
+#define HAL_DFLT_CFG_PKT_ERROR_ISR_THREAD_PRI (80)
/* PKT definitions */
#define HAL_TAU_PKT_TX_MAX_LEN (9216)
@@ -300,29 +300,29 @@ typedef struct
/* PDMA Definitions */
#define HAL_TAU_PKT_PDMA_MAX_GPD_PER_PKT (10) /* <= 256 */
-#define HAL_TAU_PKT_PDMA_TX_GPD_NUM (1024) /* <= 65535 */
-#define HAL_TAU_PKT_PDMA_RX_GPD_NUM (1024) /* <= 65535 */
+#define HAL_DFLT_CFG_PKT_TX_GPD_NUM (1024) /* <= 65535 */
+#define HAL_DFLT_CFG_PKT_RX_GPD_NUM (1024) /* <= 65535 */
#define HAL_TAU_PKT_PDMA_TX_INTR_TIMEOUT (10 * 1000) /* us */
#define HAL_TAU_PKT_PDMA_TX_POLL_MAX_LOOP (10 * 1000) /* int */
/* Mode */
#define HAL_TAU_PKT_TX_WAIT_MODE (HAL_TAU_PKT_TX_WAIT_ASYNC)
-#define HAL_TAU_PKT_RX_SCHED_MODE (HAL_TAU_PKT_RX_SCHED_RR)
+#define HAL_DFLT_CFG_PKT_RX_SCHED_MODE (HAL_TAU_PKT_RX_SCHED_RR)
/* TX Queue */
-#define HAL_TAU_PKT_TX_QUEUE_LEN (HAL_TAU_PKT_PDMA_TX_GPD_NUM * 10)
-#define HAL_TAU_PKT_TX_TASK_MAX_LOOP (HAL_TAU_PKT_TX_QUEUE_LEN)
+#define HAL_DFLT_CFG_PKT_TX_QUEUE_LEN (HAL_DFLT_CFG_PKT_TX_GPD_NUM * 10)
+#define HAL_TAU_PKT_TX_TASK_MAX_LOOP (HAL_DFLT_CFG_PKT_TX_QUEUE_LEN)
/* RX Queue */
#define HAL_TAU_PKT_RX_QUEUE_NUM (HAL_TAU_PKT_RX_CHANNEL_LAST)
-#define HAL_TAU_PKT_RX_QUEUE_WEIGHT (10)
-#define HAL_TAU_PKT_RX_QUEUE_LEN (HAL_TAU_PKT_PDMA_RX_GPD_NUM * 10)
-#define HAL_TAU_PKT_RX_TASK_MAX_LOOP (HAL_TAU_PKT_RX_QUEUE_LEN)
+#define HAL_DFLT_CFG_PKT_RX_QUEUE_WEIGHT (10)
+#define HAL_DFLT_CFG_PKT_RX_QUEUE_LEN (HAL_DFLT_CFG_PKT_RX_GPD_NUM * 10)
+#define HAL_TAU_PKT_RX_TASK_MAX_LOOP (HAL_DFLT_CFG_PKT_RX_QUEUE_LEN)
/* MACRO FUNCTION DECLARATIONS
*/
/*---------------------------------------------------------------------------*/
-/* [Taurus] Alignment to 64-bytes */
+/* [NP8360] Alignment to 64-bytes */
#if defined(NPS_EN_HOST_64_BIT_BIG_ENDIAN) || defined(NPS_EN_HOST_64_BIT_LITTLE_ENDIAN)
#define HAL_TAU_PKT_PDMA_ALIGN_ADDR(pdma_addr, align_sz) (((pdma_addr) + (align_sz)) & 0xFFFFFFFFFFFFFFC0)
#else
@@ -1120,77 +1120,77 @@ typedef struct
/* ----------------------------------------------------------------------------------- Reg Type */
typedef enum
{
- HAL_TAU_PKT_L2_ISR_RCH0 = (0x1 << 0),
- HAL_TAU_PKT_L2_ISR_RCH1 = (0x1 << 1),
- HAL_TAU_PKT_L2_ISR_RCH2 = (0x1 << 2),
- HAL_TAU_PKT_L2_ISR_RCH3 = (0x1 << 3),
- HAL_TAU_PKT_L2_ISR_TCH0 = (0x1 << 4),
- HAL_TAU_PKT_L2_ISR_TCH1 = (0x1 << 5),
- HAL_TAU_PKT_L2_ISR_TCH2 = (0x1 << 6),
- HAL_TAU_PKT_L2_ISR_TCH3 = (0x1 << 7),
- HAL_TAU_PKT_L2_ISR_RX_QID_MAP_ERR = (0x1 << 8),
- HAL_TAU_PKT_L2_ISR_RX_FRAME_ERR = (0x1 << 9)
+ HAL_TAU_PKT_L2_ISR_RCH0 = (0x1UL << 0),
+ HAL_TAU_PKT_L2_ISR_RCH1 = (0x1UL << 1),
+ HAL_TAU_PKT_L2_ISR_RCH2 = (0x1UL << 2),
+ HAL_TAU_PKT_L2_ISR_RCH3 = (0x1UL << 3),
+ HAL_TAU_PKT_L2_ISR_TCH0 = (0x1UL << 4),
+ HAL_TAU_PKT_L2_ISR_TCH1 = (0x1UL << 5),
+ HAL_TAU_PKT_L2_ISR_TCH2 = (0x1UL << 6),
+ HAL_TAU_PKT_L2_ISR_TCH3 = (0x1UL << 7),
+ HAL_TAU_PKT_L2_ISR_RX_QID_MAP_ERR = (0x1UL << 8),
+ HAL_TAU_PKT_L2_ISR_RX_FRAME_ERR = (0x1UL << 9)
} HAL_TAU_PKT_L2_ISR_T;
typedef enum
{
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_HWO_ERROR = (0x1 << 0), /* Tx GPD.hwo = 0 */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_CHKSM_ERROR = (0x1 << 1), /* Tx GPD.chksm is error */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_NO_OVFL_ERROR = (0x1 << 2), /* S/W push too much GPD */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_DMA_READ_ERROR = (0x1 << 3), /* AXI Rd Error when do GPD read */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_BUF_SIZE_ERROR = (0x1 << 4), /* Tx GPD.data_buf_size = 0 */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_RUNT_ERROR = (0x1 << 5), /* Tx GPD.pkt_len < 64 */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_OVSZ_ERROR = (0x1 << 6), /* Tx GPD.pkt_len = 9217 */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_LEN_MISMATCH_ERROR = (0x1 << 7), /* Tx GPD.pkt_len != sum of data_buf_size */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_PKTPL_DMA_READ_ERROR = (0x1 << 8), /* AXI Rd Error when do Payload read */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_COS_ERROR = (0x1 << 9), /* Tx GPD.cos is not match cos_to_tch_map */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_GT255_ERROR = (0x1 << 10), /* Multi-GPD packet's GPD# > 255 */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_PFC = (0x1 << 11), /* */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_CREDIT_UDFL_ERROR = (0x1 << 12), /* Credit Underflow (count down to 0) */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_DMA_WRITE_ERROR = (0x1 << 13), /* AXI Wr Error (GPD Write-Back) */
- HAL_TAU_PKT_TX_CHANNEL_L2_ISR_STOP_CMD_CPLT = (0x1 << 14)
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_HWO_ERROR = (0x1UL << 0), /* Tx GPD.hwo = 0 */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_CHKSM_ERROR = (0x1UL << 1), /* Tx GPD.chksm is error */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_NO_OVFL_ERROR = (0x1UL << 2), /* S/W push too much GPD */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_DMA_READ_ERROR = (0x1UL << 3), /* AXI Rd Error when do GPD read */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_BUF_SIZE_ERROR = (0x1UL << 4), /* Tx GPD.data_buf_size = 0 */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_RUNT_ERROR = (0x1UL << 5), /* Tx GPD.pkt_len < 64 */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_OVSZ_ERROR = (0x1UL << 6), /* Tx GPD.pkt_len = 9217 */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_LEN_MISMATCH_ERROR = (0x1UL << 7), /* Tx GPD.pkt_len != sum of data_buf_size */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_PKTPL_DMA_READ_ERROR = (0x1UL << 8), /* AXI Rd Error when do Payload read */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_COS_ERROR = (0x1UL << 9), /* Tx GPD.cos is not match cos_to_tch_map */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_GT255_ERROR = (0x1UL << 10), /* Multi-GPD packet's GPD# > 255 */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_PFC = (0x1UL << 11), /* */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_CREDIT_UDFL_ERROR = (0x1UL << 12), /* Credit Underflow (count down to 0) */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_DMA_WRITE_ERROR = (0x1UL << 13), /* AXI Wr Error (GPD Write-Back) */
+ HAL_TAU_PKT_TX_CHANNEL_L2_ISR_STOP_CMD_CPLT = (0x1UL << 14)
} HAL_TAU_PKT_TX_CHANNEL_L2_ISR_T;
typedef enum
{
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_LOW = (0x1 << 0), /* Rx GPD.avbl_gpd_num < threshold */
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_EMPTY = (0x1 << 1), /* Rx GPD.avbl_gpd_num = 0 */
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_ERROR = (0x1 << 2), /* Rx GPD.hwo = 0 */
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_GPD_CHKSM_ERROR = (0x1 << 3), /* Rx GPD.chksm is error */
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_DMA_READ_ERROR = (0x1 << 4), /* DMAR error occurs in PCIE */
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_DMA_WRITE_ERROR = (0x1 << 5), /* DMAW error occurs in PCIE */
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_STOP_CMD_CPLT = (0x1 << 6), /* Stop Completion Acknowledge */
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_GPD_GT255_ERROR = (0x1 << 7), /* Multi-GPD packet's GPD# > 255 */
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_TOD_UNINIT = (0x1 << 8), /* */
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_PKT_ERROR_DROP = (0x1 << 9), /* */
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_UDSZ_DROP = (0x1 << 10), /* */
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_OVSZ_DROP = (0x1 << 11), /* */
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_CMDQ_OVF_DROP = (0x1 << 12), /* */
- HAL_TAU_PKT_RX_CHANNEL_L2_ISR_FIFO_OVF_DROP = (0x1 << 13)
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_LOW = (0x1UL << 0), /* Rx GPD.avbl_gpd_num < threshold */
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_EMPTY = (0x1UL << 1), /* Rx GPD.avbl_gpd_num = 0 */
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_ERROR = (0x1UL << 2), /* Rx GPD.hwo = 0 */
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_GPD_CHKSM_ERROR = (0x1UL << 3), /* Rx GPD.chksm is error */
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_DMA_READ_ERROR = (0x1UL << 4), /* DMAR error occurs in PCIE */
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_DMA_WRITE_ERROR = (0x1UL << 5), /* DMAW error occurs in PCIE */
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_STOP_CMD_CPLT = (0x1UL << 6), /* Stop Completion Acknowledge */
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_GPD_GT255_ERROR = (0x1UL << 7), /* Multi-GPD packet's GPD# > 255 */
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_TOD_UNINIT = (0x1UL << 8), /* */
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_PKT_ERROR_DROP = (0x1UL << 9), /* */
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_UDSZ_DROP = (0x1UL << 10), /* */
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_OVSZ_DROP = (0x1UL << 11), /* */
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_CMDQ_OVF_DROP = (0x1UL << 12), /* */
+ HAL_TAU_PKT_RX_CHANNEL_L2_ISR_FIFO_OVF_DROP = (0x1UL << 13)
} HAL_TAU_PKT_RX_CHANNEL_L2_ISR_T;
typedef enum
{
- HAL_TAU_PKT_TX_CHANNEL_CFG_IOC = (0x1 << 0),
- HAL_TAU_PKT_TX_CHANNEL_CFG_CHKSUM = (0x1 << 1),
- HAL_TAU_PKT_TX_CHANNEL_CFG_PFC = (0x1 << 2),
- HAL_TAU_PKT_TX_CHANNEL_CFG_PKT_LEN_CHK = (0x1 << 3),
- HAL_TAU_PKT_TX_CHANNEL_CFG_EARLY_DONE_IRQ = (0x1 << 4),
- HAL_TAU_PKT_TX_CHANNEL_CFG_CHK_COS = (0x1 << 5),
- HAL_TAU_PKT_TX_CHANNEL_CFG_ADV_GPD_WRBK = (0x1 << 6),
- HAL_TAU_PKT_TX_CHANNEL_CFG_GPD_WRBK_FULL_PKT_LEN = (0x1 << 7),
- HAL_TAU_PKT_TX_CHANNEL_CFG_LAST = (0x1 << 8)
+ HAL_TAU_PKT_TX_CHANNEL_CFG_IOC = (0x1UL << 0),
+ HAL_TAU_PKT_TX_CHANNEL_CFG_CHKSUM = (0x1UL << 1),
+ HAL_TAU_PKT_TX_CHANNEL_CFG_PFC = (0x1UL << 2),
+ HAL_TAU_PKT_TX_CHANNEL_CFG_PKT_LEN_CHK = (0x1UL << 3),
+ HAL_TAU_PKT_TX_CHANNEL_CFG_EARLY_DONE_IRQ = (0x1UL << 4),
+ HAL_TAU_PKT_TX_CHANNEL_CFG_CHK_COS = (0x1UL << 5),
+ HAL_TAU_PKT_TX_CHANNEL_CFG_ADV_GPD_WRBK = (0x1UL << 6),
+ HAL_TAU_PKT_TX_CHANNEL_CFG_GPD_WRBK_FULL_PKT_LEN = (0x1UL << 7),
+ HAL_TAU_PKT_TX_CHANNEL_CFG_LAST = (0x1UL << 8)
} HAL_TAU_PKT_TX_CHANNEL_CFG_T;
typedef enum
{
- HAL_TAU_PKT_RX_CHANNEL_CFG_IOC = (0x1 << 0),
- HAL_TAU_PKT_RX_CHANNEL_CFG_CHKSUM = (0x1 << 1),
- HAL_TAU_PKT_RX_CHANNEL_CFG_LAST = (0x1 << 2)
+ HAL_TAU_PKT_RX_CHANNEL_CFG_IOC = (0x1UL << 0),
+ HAL_TAU_PKT_RX_CHANNEL_CFG_CHKSUM = (0x1UL << 1),
+ HAL_TAU_PKT_RX_CHANNEL_CFG_LAST = (0x1UL << 2)
} HAL_TAU_PKT_RX_CHANNEL_CFG_T;
@@ -2079,34 +2079,56 @@ typedef struct
/* metadata */
UI8_T mac[6];
-#define HAL_TAU_PKT_NETIF_INTF_FLAGS_MAC (1 << 0)
+#define HAL_TAU_PKT_NETIF_INTF_FLAGS_MAC (1UL << 0)
UI32_T flags;
} HAL_TAU_PKT_NETIF_INTF_T;
+#if defined(NETIF_EN_NETLINK)
+typedef struct
+{
+ C8_T name[NPS_NETIF_NAME_LEN];
+ C8_T mc_group_name[NPS_NETIF_NAME_LEN];
+} HAL_TAU_PKT_NETIF_RX_DST_NETLINK_T;
+#endif
+
+typedef enum
+{
+ HAL_TAU_PKT_NETIF_RX_DST_SDK = 0,
+#if defined(NETIF_EN_NETLINK)
+ HAL_TAU_PKT_NETIF_RX_DST_NETLINK,
+#endif
+ HAL_TAU_PKT_NETIF_RX_DST_LAST
+} HAL_TAU_PKT_NETIF_RX_DST_TYPE_T;
+
typedef struct
{
/* unique key */
- UI32_T id;
- C8_T name[NPS_NETIF_NAME_LEN];
- UI32_T priority;
+ UI32_T id;
+ C8_T name[NPS_NETIF_NAME_LEN];
+ UI32_T priority;
/* match fields */
- UI32_T port; /* only support unit port and local port */
- HAL_TAU_PKT_RX_REASON_BITMAP_T reason_bitmap;
- UI8_T pattern[NPS_NETIF_PROFILE_PATTERN_NUM][NPS_NETIF_PROFILE_PATTERN_LEN];
- UI8_T mask[NPS_NETIF_PROFILE_PATTERN_NUM][NPS_NETIF_PROFILE_PATTERN_LEN];
- UI32_T offset[NPS_NETIF_PROFILE_PATTERN_NUM];
+ UI32_T port; /* only support unit port and local port */
+ HAL_PKT_RX_REASON_BITMAP_T reason_bitmap;
+ UI8_T pattern[NPS_NETIF_PROFILE_PATTERN_NUM][NPS_NETIF_PROFILE_PATTERN_LEN];
+ UI8_T mask[NPS_NETIF_PROFILE_PATTERN_NUM][NPS_NETIF_PROFILE_PATTERN_LEN];
+ UI32_T offset[NPS_NETIF_PROFILE_PATTERN_NUM];
/* for each flag 1:must hit, 0:don't care */
-#define HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PORT (1 << 0)
-#define HAL_TAU_PKT_NETIF_PROFILE_FLAGS_REASON (1 << 1)
-#define HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PATTERN_0 (1 << 2)
-#define HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PATTERN_1 (1 << 3)
-#define HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PATTERN_2 (1 << 4)
-#define HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PATTERN_3 (1 << 5)
- UI32_T flags;
+#define HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PORT (1UL << 0)
+#define HAL_TAU_PKT_NETIF_PROFILE_FLAGS_REASON (1UL << 1)
+#define HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PATTERN_0 (1UL << 2)
+#define HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PATTERN_1 (1UL << 3)
+#define HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PATTERN_2 (1UL << 4)
+#define HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PATTERN_3 (1UL << 5)
+ UI32_T flags;
+
+ HAL_TAU_PKT_NETIF_RX_DST_TYPE_T dst_type;
+#if defined(NETIF_EN_NETLINK)
+ HAL_TAU_PKT_NETIF_RX_DST_NETLINK_T netlink;
+#endif
} HAL_TAU_PKT_NETIF_PROFILE_T;
@@ -2141,6 +2163,13 @@ typedef enum
HAL_TAU_PKT_IOCTL_TYPE_CLEAR_RX_CNT,
/* port attribute */
HAL_TAU_PKT_IOCTL_TYPE_SET_PORT_ATTR,
+#if defined(NETIF_EN_NETLINK)
+ HAL_TAU_PKT_IOCTL_TYPE_NL_SET_INTF_PROPERTY,
+ HAL_TAU_PKT_IOCTL_TYPE_NL_GET_INTF_PROPERTY,
+ HAL_TAU_PKT_IOCTL_TYPE_NL_CREATE_NETLINK,
+ HAL_TAU_PKT_IOCTL_TYPE_NL_DESTROY_NETLINK,
+ HAL_TAU_PKT_IOCTL_TYPE_NL_GET_NETLINK,
+#endif
HAL_TAU_PKT_IOCTL_TYPE_LAST
} HAL_TAU_PKT_IOCTL_TYPE_T;
@@ -2219,6 +2248,51 @@ typedef struct
} HAL_TAU_PKT_IOCTL_PORT_COOKIE_T;
+#if defined(NETIF_EN_NETLINK)
+
+#define NPS_NETIF_NETLINK_NUM_MAX (256)
+#define NPS_NETIF_NETLINK_MC_GROUP_NUM_MAX (32)
+
+typedef enum
+{
+ NPS_NETIF_INTF_PROPERTY_IGR_SAMPLING_RATE,
+ NPS_NETIF_INTF_PROPERTY_EGR_SAMPLING_RATE,
+ NPS_NETIF_INTF_PROPERTY_LAST
+} NPS_NETIF_INTF_PROPERTY_T;
+
+typedef struct
+{
+ C8_T name[NPS_NETIF_NAME_LEN];
+
+} NPS_NETIF_NETLINK_MC_GROUP_T;
+
+typedef struct
+{
+ UI32_T id;
+ C8_T name[NPS_NETIF_NAME_LEN];
+ NPS_NETIF_NETLINK_MC_GROUP_T mc_group[NPS_NETIF_NETLINK_MC_GROUP_NUM_MAX];
+ UI32_T mc_group_num;
+
+} NPS_NETIF_NETLINK_T;
+
+typedef struct
+{
+ /* intf property */
+ UI32_T intf_id;
+ NPS_NETIF_INTF_PROPERTY_T property;
+ UI32_T param0;
+ UI32_T param1;
+
+ /* netlink */
+ NPS_NETIF_NETLINK_T netlink;
+
+ NPS_ERROR_NO_T rc;
+
+} HAL_TAU_PKT_NL_IOCTL_COOKIE_T;
+
+
+#endif /* End of NETIF_EN_NETLINK */
+
typedef union
{
UI32_T value;
@@ -2231,6 +2305,7 @@ typedef union
} HAL_TAU_PKT_IOCTL_CMD_T;
+
#endif /* End of NPS_EN_NETIF */
NPS_ERROR_NO_T
diff --git a/platform/nephos/nephos-modules/modules/src/inc/netif_nl.h b/platform/nephos/nephos-modules/modules/src/inc/netif_nl.h
new file mode 100755
index 000000000000..4b31ceef1620
--- /dev/null
+++ b/platform/nephos/nephos-modules/modules/src/inc/netif_nl.h
@@ -0,0 +1,104 @@
+/* Copyright (C) 2020 MediaTek, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program.
+ */
+
+ /* FILE NAME: netif_nl.h
+ * PURPOSE:
+ * It provide xxx API.
+ * NOTES:
+ */
+
+#ifndef NETIF_NL_H
+#define NETIF_NL_H
+
+#include
+
+#define NETIF_NL_NETLINK_MC_GROUP_NUM (32)
+#define NETIF_NL_NETLINK_NAME_LEN (16)
+
+typedef enum
+{
+ NETIF_NL_INTF_PROPERTY_IGR_SAMPLING_RATE,
+ NETIF_NL_INTF_PROPERTY_EGR_SAMPLING_RATE,
+ NETIF_NL_INTF_PROPERTY_LAST
+} NETIF_NL_INTF_PROPERTY_T;
+
+/* must be the same with NPS_NETIF_RX_DST_NETLINK_T */
+typedef struct
+{
+ C8_T name[NETIF_NL_NETLINK_NAME_LEN];
+ C8_T mc_group_name[NETIF_NL_NETLINK_NAME_LEN];
+} NETIF_NL_RX_DST_NETLINK_T;
+
+/* must be the same with NPS_NETIF_NETLINK_MC_GROUP_T */
+typedef struct
+{
+ C8_T name[NETIF_NL_NETLINK_NAME_LEN];
+
+} NETIF_NL_NETLINK_MC_GROUP_T;
+
+/* must be the same with NPS_NETIF_NETLINK_T */
+typedef struct
+{
+ UI32_T id;
+ C8_T name[NETIF_NL_NETLINK_NAME_LEN];
+ NETIF_NL_NETLINK_MC_GROUP_T mc_group[NETIF_NL_NETLINK_MC_GROUP_NUM];
+ UI32_T mc_group_num;
+
+} NETIF_NL_NETLINK_T;
+
+NPS_ERROR_NO_T
+netif_nl_rxSkb(
+ const UI32_T unit,
+ struct sk_buff *ptr_skb,
+ void *ptr_cookie);
+
+NPS_ERROR_NO_T
+netif_nl_setIntfProperty(
+ const UI32_T unit,
+ const UI32_T id,
+ const NETIF_NL_INTF_PROPERTY_T property,
+ const UI32_T param0,
+ const UI32_T param1);
+
+NPS_ERROR_NO_T
+netif_nl_getIntfProperty(
+ const UI32_T unit,
+ const UI32_T port,
+ const NETIF_NL_INTF_PROPERTY_T property,
+ UI32_T *ptr_param0,
+ UI32_T *ptr_param1);
+
+NPS_ERROR_NO_T
+netif_nl_createNetlink(
+ const UI32_T unit,
+ NETIF_NL_NETLINK_T *ptr_netlink,
+ UI32_T *ptr_netlink_id);
+
+NPS_ERROR_NO_T
+netif_nl_destroyNetlink(
+ const UI32_T unit,
+ const UI32_T group_id);
+
+NPS_ERROR_NO_T
+netif_nl_getNetlink(
+ const UI32_T unit,
+ const UI32_T netlink_id,
+ NETIF_NL_NETLINK_T *ptr_netlink);
+
+
+NPS_ERROR_NO_T
+netif_nl_init(void);
+
+#endif /* end of NETIF_NL_H */
diff --git a/platform/nephos/nephos-modules/modules/src/inc/netif_osal.h b/platform/nephos/nephos-modules/modules/src/inc/netif_osal.h
index 40c8c9ebc358..93f30fc61ce1 100755
--- a/platform/nephos/nephos-modules/modules/src/inc/netif_osal.h
+++ b/platform/nephos/nephos-modules/modules/src/inc/netif_osal.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/platform/nephos/nephos-modules/modules/src/inc/netif_perf.h b/platform/nephos/nephos-modules/modules/src/inc/netif_perf.h
index 35596668ba9d..5309f01b62d8 100755
--- a/platform/nephos/nephos-modules/modules/src/inc/netif_perf.h
+++ b/platform/nephos/nephos-modules/modules/src/inc/netif_perf.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/platform/nephos/nephos-modules/modules/src/inc/nps_cfg.h b/platform/nephos/nephos-modules/modules/src/inc/nps_cfg.h
index 34306344c55a..36de3cc70863 100755
--- a/platform/nephos/nephos-modules/modules/src/inc/nps_cfg.h
+++ b/platform/nephos/nephos-modules/modules/src/inc/nps_cfg.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/platform/nephos/nephos-modules/modules/src/inc/nps_error.h b/platform/nephos/nephos-modules/modules/src/inc/nps_error.h
index 261878abf3cb..3cf0a14adc0b 100755
--- a/platform/nephos/nephos-modules/modules/src/inc/nps_error.h
+++ b/platform/nephos/nephos-modules/modules/src/inc/nps_error.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/platform/nephos/nephos-modules/modules/src/inc/nps_types.h b/platform/nephos/nephos-modules/modules/src/inc/nps_types.h
index 5630b521404e..88100f69738f 100755
--- a/platform/nephos/nephos-modules/modules/src/inc/nps_types.h
+++ b/platform/nephos/nephos-modules/modules/src/inc/nps_types.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/platform/nephos/nephos-modules/modules/src/inc/osal_mdc.h b/platform/nephos/nephos-modules/modules/src/inc/osal_mdc.h
index 47971bb38c8d..0add2c8216b1 100755
--- a/platform/nephos/nephos-modules/modules/src/inc/osal_mdc.h
+++ b/platform/nephos/nephos-modules/modules/src/inc/osal_mdc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -134,6 +134,8 @@ typedef enum
OSAL_MDC_IOCTL_TYPE_MDC_FREE_SYS_DMA_MEM,
OSAL_MDC_IOCTL_TYPE_MDC_CONNECT_ISR,
OSAL_MDC_IOCTL_TYPE_MDC_DISCONNECT_ISR,
+ OSAL_MDC_IOCTL_TYPE_MDC_SAVE_PCI_CONFIG,
+ OSAL_MDC_IOCTL_TYPE_MDC_RESTORE_PCI_CONFIG,
OSAL_MDC_IOCTL_TYPE_LAST
} OSAL_MDC_IOCTL_TYPE_T;
@@ -238,4 +240,12 @@ osal_mdc_invalidateCache(
void *ptr_virt_addr,
const UI32_T size);
+NPS_ERROR_NO_T
+osal_mdc_savePciConfig(
+ const UI32_T unit);
+
+NPS_ERROR_NO_T
+osal_mdc_restorePciConfig(
+ const UI32_T unit);
+
#endif /* OSAL_MDC_H */
diff --git a/platform/nephos/nephos-modules/modules/src/inc/osal_types.h b/platform/nephos/nephos-modules/modules/src/inc/osal_types.h
index 48ac58aba335..59fd3df1260d 100755
--- a/platform/nephos/nephos-modules/modules/src/inc/osal_types.h
+++ b/platform/nephos/nephos-modules/modules/src/inc/osal_types.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/platform/nephos/nephos-modules/modules/src/make.mk b/platform/nephos/nephos-modules/modules/src/make.mk
index e556ea10d765..b49da8b43cdf 100755
--- a/platform/nephos/nephos-modules/modules/src/make.mk
+++ b/platform/nephos/nephos-modules/modules/src/make.mk
@@ -1,5 +1,5 @@
################################################################################
-# Copyright (C) 2019 Nephos, Inc.
+# Copyright (C) 2020 MediaTek, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -17,7 +17,7 @@ DEV_MODULE_NAME := nps_dev
NETIF_MODULE_NAME := nps_netif
################################################################################
DEV_OBJS_TOTAL := ./src/osal_mdc.o ./src/osal_isymbol.o
-NETIF_OBJS_TOTAL := ./src/hal_tau_pkt_knl.o ./src/netif_perf.o ./src/netif_osal.o
+NETIF_OBJS_TOTAL := ./src/hal_tau_pkt_knl.o ./src/netif_perf.o ./src/netif_osal.o ./src/netif_nl.o
obj-m := $(DEV_MODULE_NAME).o $(NETIF_MODULE_NAME).o
$(DEV_MODULE_NAME)-objs := $(DEV_OBJS_TOTAL)
diff --git a/platform/nephos/nephos-modules/modules/src/netif_nl.c b/platform/nephos/nephos-modules/modules/src/netif_nl.c
new file mode 100755
index 000000000000..c112e4b6dd80
--- /dev/null
+++ b/platform/nephos/nephos-modules/modules/src/netif_nl.c
@@ -0,0 +1,811 @@
+/* Copyright (C) 2020 MediaTek, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program.
+ */
+
+ /* FILE NAME: netif_xxx.c
+ * PURPOSE:
+ * It provide xxx API.
+ * NOTES:
+ */
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+extern UI32_T ext_dbg_flag;
+
+#define NETIF_NL_DBG(__flag__, ...) do \
+{ \
+ if (0 != ((__flag__) & (ext_dbg_flag))) \
+ { \
+ osal_printf(__VA_ARGS__); \
+ } \
+}while (0)
+
+#define NETIF_NL_DBG_NETLINK (0x1UL << 6)
+
+#define NETIF_NL_FAMILY_NUM_MAX (256)
+#define NETIF_NL_INTF_NUM_MAX (256)
+
+#define NETIF_NL_GET_FAMILY_META(__idx__) &(_netif_nl_cb.fam_entry[__idx__].meta)
+#define NETIF_NL_GET_INTF_IGR_SAMPLE_RATE(__inft_id__) (_netif_nl_cb.intf_entry[__inft_id__].igr_sample_rate)
+
+#define NETIF_NL_FAMILY_IS_PSAMPLE(__ptr_family__) (0 == strncmp(__ptr_family__->name, \
+ NETIF_NL_PSAMPLE_FAMILY_NAME, \
+ NETIF_NL_NETLINK_NAME_LEN)) ? 1 : 0
+
+/* porting part */
+#define NETIF_NL_VER_NUM (1)
+#define NETIF_NL_PSAMPLE_MAX_ATTR_NUM (NETIF_NL_PSAMPLE_ATTR_LAST)
+#define NETIF_NL_REGISTER_FAMILY(__family__) genl_register_family(__family__)
+
+#define NETIF_NL_UNREGISTER_FAMILY(__family__) genl_unregister_family(__family__)
+#define NETIF_NL_ALLOC_SKB(__len__) genlmsg_new(__len__, GFP_ATOMIC)
+#define NETIF_NL_FREE_SKB(__ptr_skb__) nlmsg_free(__ptr_skb__)
+
+#define NETIF_NL_SEND_PKT(__ptr_family__, __mcgrp_id__, __ptr_skb__) \
+ genlmsg_multicast_netns(__ptr_family__, \
+ &init_net, \
+ __ptr_skb__, \
+ 0, /* pid, avoid loop */ \
+ __mcgrp_id__, \
+ GFP_ATOMIC)
+#define NETIF_NL_SET_SKB_ATTR_HDR(__skb__, __family__, __hdr_len__, __cmd__) \
+ genlmsg_put(__skb__, 0, 0, __family__, \
+ __hdr_len__, __cmd__)
+#define NETIF_NL_END_SKB_ATTR_HDR(__skb__, __hdr__) genlmsg_end(__skb__, __hdr__)
+
+#define NETIF_NL_SET_16_BIT_ATTR(__skb__, __attr__, __data__) nla_put_u16(__skb__, __attr__, __data__)
+#define NETIF_NL_SET_32_BIT_ATTR(__skb__, __attr__, __data__) nla_put_u32(__skb__, __attr__, __data__)
+
+
+/*
+ * <----------- nla_total_size(payload) ------------->
+ * +------------------+- - -+- - - - - - - - - +- - -+
+ * | Attribute Header | Pad | Payload | Pad |
+ * +------------------+- - -+- - - - - - - - - +- - -+
+ *
+ *
+ * <-------- nla_attr_size(payload) ---------->
+ * +------------------+- - -+- - - - - - - - - +- - -+
+ * | Attribute Header | Pad | Payload | Pad |
+ * +------------------+- - -+- - - - - - - - - +- - -+
+ *
+ */
+/* total size = attr data size + attr header size */
+#define NETIF_NL_GET_ATTR_TOTAL_SIZE(__data_size__) nla_total_size(__data_size__)
+#define NETIF_NL_GET_ATTR_SIZE(__data_size__) nla_attr_size(__data_size__) /* without padding */
+
+
+/* psample's family and group parameter */
+#define NETIF_NL_PSAMPLE_FAMILY_NAME "psample"
+#define NETIF_NL_PSAMPLE_MC_GROUP_NAME_DATA "packets"
+#define NETIF_NL_PSAMPLE_MC_GROUP_NAME_CFG "config"
+#define NETIF_NL_PSAMPLE_MC_GROUP_NUM (NETIF_NL_PSAMPLE_MC_GROUP_ID_LAST)
+#define NETIF_NL_DEFAULT_MC_GROUP_NUM (1)
+
+#define NETIF_NL_PSAMPLE_PKT_LEN_MAX (9216)
+#define NETIF_NL_PSAMPLE_DFLT_USR_GROUP_ID (1)
+
+typedef enum
+{
+ NETIF_NL_PSAMPLE_MC_GROUP_ID_CONFIG = 0,
+ NETIF_NL_PSAMPLE_MC_GROUP_ID_SAMPLE,
+ NETIF_NL_PSAMPLE_MC_GROUP_ID_LAST,
+} NETIF_NL_PSAMPLE_MC_GROUP_ID_T;
+
+typedef enum
+{
+ NETIF_NL_PSAMPLE_ATTR_IIFINDEX = 0,
+ NETIF_NL_PSAMPLE_ATTR_OIFINDEX,
+ NETIF_NL_PSAMPLE_ATTR_ORIGSIZE,
+ NETIF_NL_PSAMPLE_ATTR_SAMPLE_GROUP,
+ NETIF_NL_PSAMPLE_ATTR_GROUP_SEQ,
+ NETIF_NL_PSAMPLE_ATTR_SAMPLE_RATE,
+ NETIF_NL_PSAMPLE_ATTR_DATA,
+ NETIF_NL_PSAMPLE_ATTR_LAST
+} NETIF_NL_PSAMPLE_ATTR_ID_T;
+
+
+typedef struct genl_multicast_group NETIF_NL_MC_GROUP_T;
+typedef struct genl_family NETIF_NL_FAMILY_T;
+
+static NETIF_NL_MC_GROUP_T _netif_nl_psample_mc_group[NETIF_NL_PSAMPLE_MC_GROUP_ID_LAST];
+static C8_T *_ptr_netif_nl_psample_mc_group_name[NETIF_NL_PSAMPLE_MC_GROUP_ID_LAST] =
+ {
+ NETIF_NL_PSAMPLE_MC_GROUP_NAME_CFG,
+ NETIF_NL_PSAMPLE_MC_GROUP_NAME_DATA
+ };
+
+static NETIF_NL_MC_GROUP_T _netif_nl_default_mc_group[NETIF_NL_DEFAULT_MC_GROUP_NUM];
+static C8_T *_ptr_netif_nl_default_mc_group_name[NETIF_NL_DEFAULT_MC_GROUP_NUM] =
+ {
+ "default",
+ };
+
+typedef struct
+{
+ NETIF_NL_FAMILY_T meta;
+ BOOL_T valid;
+
+} NETIF_NL_FAMILY_ENTRY_T;
+
+typedef struct
+{
+ UI32_T igr_sample_rate;
+ UI32_T egr_sample_rate;
+ UI32_T trunc_size;
+} NETIF_NL_INTF_ENTRY_T;
+
+typedef struct
+{
+ NETIF_NL_FAMILY_ENTRY_T fam_entry[NETIF_NL_FAMILY_NUM_MAX];
+ NETIF_NL_INTF_ENTRY_T intf_entry[NETIF_NL_INTF_NUM_MAX]; /* sorted in intf_id */
+ UI32_T seq_num;
+} NETIF_NL_CB_T;
+
+static NETIF_NL_CB_T _netif_nl_cb;
+
+/* should extract to common */
+struct net_device_priv
+{
+ struct net_device *ptr_net_dev;
+ struct net_device_stats stats;
+ UI32_T unit;
+ UI32_T id;
+ UI32_T port;
+ UI16_T vlan;
+ UI32_T speed;
+};
+
+static NPS_ERROR_NO_T
+_netif_nl_setIntfIgrSampleRate(
+ const UI32_T unit,
+ const UI32_T id,
+ const UI32_T rate)
+{
+ NETIF_NL_CB_T *ptr_cb = &_netif_nl_cb;
+
+ ptr_cb->intf_entry[id].igr_sample_rate = rate;
+
+ return (NPS_E_OK);
+}
+
+static NPS_ERROR_NO_T
+_netif_nl_setIntfEgrSampleRate(
+ const UI32_T unit,
+ const UI32_T id,
+ const UI32_T rate)
+{
+ NETIF_NL_CB_T *ptr_cb = &_netif_nl_cb;
+
+ ptr_cb->intf_entry[id].egr_sample_rate = rate;
+
+ return (NPS_E_OK);
+}
+
+
+NPS_ERROR_NO_T
+netif_nl_setIntfProperty(
+ const UI32_T unit,
+ const UI32_T id,
+ const NETIF_NL_INTF_PROPERTY_T property,
+ const UI32_T param0,
+ const UI32_T param1)
+{
+ NPS_ERROR_NO_T rc = NPS_E_BAD_PARAMETER;
+
+ if (NETIF_NL_INTF_PROPERTY_IGR_SAMPLING_RATE == property)
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "receive set igr sample rate req, id=%d, property=%d, param0=%d, param=%d\n",
+ id, property, param0, param1);
+ rc = _netif_nl_setIntfIgrSampleRate(unit, id, param0);
+ }
+ else if (NETIF_NL_INTF_PROPERTY_EGR_SAMPLING_RATE == property)
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "receive set egr sample rate req, id=%d, property=%d, param0=%d, param=%d\n",
+ id, property, param0, param1);
+ rc = _netif_nl_setIntfEgrSampleRate(unit, id, param0);
+ }
+ else
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[error] unknown property, property=%d\n", property);
+ }
+
+ return (rc);
+}
+
+static NPS_ERROR_NO_T
+_netif_nl_getIntfIgrSampleRate(
+ const UI32_T unit,
+ const UI32_T id,
+ UI32_T *ptr_rate)
+{
+ NETIF_NL_CB_T *ptr_cb = &_netif_nl_cb;
+
+ *ptr_rate = ptr_cb->intf_entry[id].igr_sample_rate;
+
+ return (NPS_E_OK);
+}
+
+static NPS_ERROR_NO_T
+_netif_nl_getIntfEgrSampleRate(
+ const UI32_T unit,
+ const UI32_T id,
+ UI32_T *ptr_rate)
+{
+ NETIF_NL_CB_T *ptr_cb = &_netif_nl_cb;
+
+ *ptr_rate = ptr_cb->intf_entry[id].egr_sample_rate;
+
+ return (NPS_E_OK);
+}
+
+
+NPS_ERROR_NO_T
+netif_nl_getIntfProperty(
+ const UI32_T unit,
+ const UI32_T id,
+ const NETIF_NL_INTF_PROPERTY_T property,
+ UI32_T *ptr_param0,
+ UI32_T *ptr_param1)
+{
+ NPS_ERROR_NO_T rc = NPS_E_BAD_PARAMETER;
+
+ if (NETIF_NL_INTF_PROPERTY_IGR_SAMPLING_RATE == property)
+ {
+ rc = _netif_nl_getIntfIgrSampleRate(unit, id, ptr_param0);
+ }
+ else if (NETIF_NL_INTF_PROPERTY_EGR_SAMPLING_RATE == property)
+ {
+ rc = _netif_nl_getIntfEgrSampleRate(unit, id, ptr_param0);
+ }
+ else
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[error] unknown property, property=%d\n",
+ property);
+ }
+
+ return (rc);
+}
+
+NPS_ERROR_NO_T
+_netif_nl_allocNlFamilyEntry(
+ NETIF_NL_CB_T *ptr_cb,
+ UI32_T *ptr_index)
+{
+ UI32_T idx;
+ NPS_ERROR_NO_T rc = NPS_E_TABLE_FULL;
+
+ for (idx = 0; idx < NETIF_NL_FAMILY_NUM_MAX; idx++)
+ {
+ if (FALSE == ptr_cb->fam_entry[idx].valid)
+ {
+ *ptr_index = idx;
+ ptr_cb->fam_entry[idx].valid = TRUE;
+ rc = NPS_E_OK;
+ break;
+ }
+ }
+
+ return (rc);
+}
+
+void
+_netif_nl_freeNlFamilyEntry(
+ NETIF_NL_CB_T *ptr_cb,
+ const UI32_T index)
+{
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[DBG] free netlink family entry, idx=%d\n",
+ index);
+ ptr_cb->fam_entry[index].valid = FALSE;
+}
+
+NPS_ERROR_NO_T
+_netif_nl_setNlMcgroupPsample(
+ NETIF_NL_FAMILY_T *ptr_nl_family)
+{
+ NETIF_NL_MC_GROUP_T *ptr_nl_mc_group = _netif_nl_psample_mc_group;
+ UI32_T idx;
+
+ /* init the mc group and hook the group to family */
+ osal_memset(ptr_nl_mc_group, 0x0,
+ (NETIF_NL_PSAMPLE_MC_GROUP_NUM * sizeof(NETIF_NL_MC_GROUP_T)));
+
+ for (idx = 0; idx < NETIF_NL_PSAMPLE_MC_GROUP_ID_LAST; idx++)
+ {
+ osal_memcpy(ptr_nl_mc_group[idx].name,
+ _ptr_netif_nl_psample_mc_group_name[idx],
+ osal_strlen(_ptr_netif_nl_psample_mc_group_name[idx]));
+ }
+ ptr_nl_family->n_mcgrps = NETIF_NL_PSAMPLE_MC_GROUP_NUM;
+ ptr_nl_family->mcgrps = ptr_nl_mc_group;
+
+ return (NPS_E_OK);
+}
+
+NPS_ERROR_NO_T
+_netif_nl_setNlMcgroupDefault(
+ NETIF_NL_FAMILY_T *ptr_nl_family)
+{
+ NETIF_NL_MC_GROUP_T *ptr_nl_mc_group = _netif_nl_default_mc_group;
+ UI32_T idx;
+
+ /* init the mc group and hook the group to family */
+ osal_memset(ptr_nl_mc_group, 0x0,
+ (NETIF_NL_DEFAULT_MC_GROUP_NUM * sizeof(NETIF_NL_MC_GROUP_T)));
+
+ for (idx = 0; idx < NETIF_NL_DEFAULT_MC_GROUP_NUM; idx++)
+ {
+ osal_memcpy(ptr_nl_mc_group[idx].name,
+ _ptr_netif_nl_default_mc_group_name[idx],
+ osal_strlen(_ptr_netif_nl_default_mc_group_name[idx]));
+ }
+ ptr_nl_family->n_mcgrps = NETIF_NL_DEFAULT_MC_GROUP_NUM;
+ ptr_nl_family->mcgrps = ptr_nl_mc_group;
+
+ return (NPS_E_OK);
+}
+
+#define NETIF_NL_IS_FAMILY_ENTRY_VALID(__idx__) \
+ (TRUE == _netif_nl_cb.fam_entry[__idx__].valid) ? (TRUE) : (FALSE)
+NPS_ERROR_NO_T
+netif_nl_createNetlink(
+ const UI32_T unit,
+ NETIF_NL_NETLINK_T *ptr_netlink,
+ UI32_T *ptr_netlink_id)
+{
+ NETIF_NL_CB_T *ptr_cb = &_netif_nl_cb;
+ UI32_T entry_id;
+ NETIF_NL_FAMILY_T *ptr_nl_family;
+ NETIF_NL_MC_GROUP_T *ptr_nl_mcgrp;
+ UI32_T idx;
+ int ret;
+ NPS_ERROR_NO_T rc;
+
+ rc = _netif_nl_allocNlFamilyEntry(ptr_cb, &entry_id);
+ if (NPS_E_OK == rc)
+ {
+ ptr_nl_family = NETIF_NL_GET_FAMILY_META(entry_id);
+
+ /* fill in the meta data for that netlink family */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
+ ptr_nl_family->id = GENL_ID_GENERATE; /* family id can be ignored since linux 4.10 */
+#endif
+ ptr_nl_family->version = NETIF_NL_VER_NUM;
+ ptr_nl_family->maxattr = NETIF_NL_PSAMPLE_MAX_ATTR_NUM;
+ ptr_nl_family->netnsok = true;
+ osal_memcpy(ptr_nl_family->name, ptr_netlink->name, NETIF_NL_NETLINK_NAME_LEN);
+
+ /* fill in the mc group info */
+ ptr_nl_mcgrp = osal_alloc(sizeof(NETIF_NL_MC_GROUP_T)*ptr_netlink->mc_group_num);
+ if (NULL != ptr_nl_mcgrp)
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK, "[DBG] create mc group:\n");
+ for (idx = 0; idx < ptr_netlink->mc_group_num; idx++)
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[DBG] - mcgrp%d: %s\n", idx, ptr_netlink->mc_group[idx].name);
+ osal_memcpy(ptr_nl_mcgrp[idx].name, ptr_netlink->mc_group[idx].name,
+ NETIF_NL_NETLINK_NAME_LEN);
+ }
+ ptr_nl_family->n_mcgrps = ptr_netlink->mc_group_num;
+ ptr_nl_family->mcgrps = ptr_nl_mcgrp;
+
+ /* register the family to kernel */
+ ret = NETIF_NL_REGISTER_FAMILY(ptr_nl_family);
+ if (0 == ret)
+ {
+ *ptr_netlink_id = entry_id;
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[DBG] create netlink family, name=%s, entry_idx=%d, mcgrp_num=%d\n",
+ ptr_netlink->name, entry_id, ptr_nl_family->n_mcgrps);
+ rc = NPS_E_OK;
+ }
+ else
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[DBG] register netlink family failed, name=%s, ret=%d\n",
+ ptr_netlink->name, ret);
+ osal_free(ptr_nl_mcgrp);
+ _netif_nl_freeNlFamilyEntry(ptr_cb, entry_id);
+ rc = NPS_E_OTHERS;
+ }
+ }
+ else
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK, "[DBG] alloc mcgrp failed\n");
+ rc = NPS_E_NO_MEMORY;
+ }
+ }
+
+ return (rc);
+}
+
+NPS_ERROR_NO_T
+netif_nl_destroyNetlink(
+ const UI32_T unit,
+ const UI32_T netlink_id)
+{
+ NETIF_NL_CB_T *ptr_cb = &_netif_nl_cb;
+ UI32_T entry_idx = netlink_id;
+ NETIF_NL_FAMILY_T *ptr_nl_family;
+ int ret;
+ NPS_ERROR_NO_T rc;
+
+ if (TRUE == NETIF_NL_IS_FAMILY_ENTRY_VALID(entry_idx))
+ {
+ ptr_nl_family = NETIF_NL_GET_FAMILY_META(entry_idx);
+ ret = NETIF_NL_UNREGISTER_FAMILY(ptr_nl_family);
+ if (0 == ret)
+ {
+ osal_free(ptr_nl_family->mcgrps);
+ _netif_nl_freeNlFamilyEntry(ptr_cb, entry_idx);
+ rc = NPS_E_OK;
+ }
+ else
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[DBG] unregister netlink family failed, name=%s, ret=%d\n",
+ ptr_nl_family->name, ret);
+ rc = NPS_E_OTHERS;
+ }
+ }
+ else
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[DBG] destroy netlink failed, invalid netlink_id %d\n",
+ netlink_id);
+ rc = NPS_E_ENTRY_NOT_FOUND;
+ }
+
+ return (rc);
+}
+
+NPS_ERROR_NO_T
+netif_nl_getNetlink(
+ const UI32_T unit,
+ const UI32_T netlink_id,
+ NETIF_NL_NETLINK_T *ptr_netlink)
+{
+ UI32_T entry_idx = netlink_id;
+ NETIF_NL_FAMILY_T *ptr_meta;
+ UI32_T grp_idx;
+ NPS_ERROR_NO_T rc = NPS_E_OK;
+
+ if (TRUE == NETIF_NL_IS_FAMILY_ENTRY_VALID(entry_idx))
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[DBG] get valid netlink, id=%d\n", netlink_id);
+
+ ptr_netlink->id = netlink_id;
+ ptr_meta = NETIF_NL_GET_FAMILY_META(entry_idx);
+
+ ptr_netlink->mc_group_num = ptr_meta->n_mcgrps;
+ osal_memcpy(ptr_netlink->name, ptr_meta->name, NETIF_NL_NETLINK_NAME_LEN);
+
+ for (grp_idx = 0; grp_idx < ptr_meta->n_mcgrps; grp_idx++)
+ {
+ osal_memcpy(ptr_netlink->mc_group[grp_idx].name,
+ ptr_meta->mcgrps[grp_idx].name,
+ NETIF_NL_NETLINK_NAME_LEN);
+ }
+ }
+ else
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[DBG] get netlink failed, invalid netlink_id %d\n",
+ netlink_id);
+ rc = NPS_E_ENTRY_NOT_FOUND;
+ }
+
+ return (rc);
+}
+
+
+NPS_ERROR_NO_T
+_netif_nl_getFamilyByName(
+ NETIF_NL_CB_T *ptr_cb,
+ const C8_T *ptr_name,
+ NETIF_NL_FAMILY_T **pptr_nl_family)
+{
+ UI32_T idx;
+ NPS_ERROR_NO_T rc = NPS_E_ENTRY_NOT_FOUND;
+
+ for (idx = 0; idx < NETIF_NL_FAMILY_NUM_MAX; idx++)
+ {
+ if ((TRUE == ptr_cb->fam_entry[idx].valid) &&
+ (0 == strncmp(ptr_cb->fam_entry[idx].meta.name,
+ ptr_name,
+ NETIF_NL_NETLINK_NAME_LEN)))
+ {
+ *pptr_nl_family = &(ptr_cb->fam_entry[idx].meta);
+ rc = NPS_E_OK;
+ break;
+ }
+ }
+
+ if (NPS_E_ENTRY_NOT_FOUND == rc)
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[DBG] find family failed, name=%s\n",
+ ptr_name);
+ }
+
+ return (rc);
+}
+
+NPS_ERROR_NO_T
+_netif_nl_getMcgrpIdByName(
+ NETIF_NL_FAMILY_T *ptr_nl_family,
+ const C8_T *ptr_mcgrp_name,
+ UI32_T *ptr_mcgrp_id)
+{
+ UI32_T idx;
+ NPS_ERROR_NO_T rc = NPS_E_ENTRY_NOT_FOUND;
+
+ for (idx = 0; idx < ptr_nl_family->n_mcgrps; idx++)
+ {
+ if ((0 == strncmp(ptr_nl_family->mcgrps[idx].name,
+ ptr_mcgrp_name,
+ NETIF_NL_NETLINK_NAME_LEN)))
+ {
+ *ptr_mcgrp_id = idx;
+ rc = NPS_E_OK;
+ break;
+ }
+ }
+
+ if (NPS_E_OK != rc)
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[DBG] find mcgrp %s failed in family %s\n",
+ ptr_mcgrp_name, ptr_nl_family->name);
+ }
+
+ return (rc);
+}
+
+NPS_ERROR_NO_T
+_netif_nl_allocPsampleSkb(
+ NETIF_NL_CB_T *ptr_cb,
+ NETIF_NL_FAMILY_T *ptr_nl_family,
+ struct sk_buff *ptr_ori_skb,
+ struct sk_buff **pptr_nl_skb)
+{
+ UI32_T msg_hdr_len;
+ UI32_T data_len;
+ struct sk_buff *ptr_nl_skb;
+ UI16_T igr_intf_idx;
+ struct net_device_priv *ptr_priv;
+ UI32_T rate;
+ UI32_T intf_id;
+ void *ptr_nl_hdr = NULL;
+ struct nlattr *ptr_nl_attr;
+ NPS_ERROR_NO_T rc = NPS_E_OK;
+
+ /* make sure the total len (original pkt len + hdr msg) < PSAMPLE_MAX_PACKET_SIZE */
+
+ msg_hdr_len = NETIF_NL_GET_ATTR_TOTAL_SIZE(sizeof(UI16_T)) + /* PSAMPLE_ATTR_IIFINDEX */
+ NETIF_NL_GET_ATTR_TOTAL_SIZE(sizeof(UI32_T)) + /* PSAMPLE_ATTR_SAMPLE_RATE */
+ NETIF_NL_GET_ATTR_TOTAL_SIZE(sizeof(UI32_T)) + /* PSAMPLE_ATTR_ORIGSIZE */
+ NETIF_NL_GET_ATTR_TOTAL_SIZE(sizeof(UI32_T)) + /* PSAMPLE_ATTR_SAMPLE_GROUP */
+ NETIF_NL_GET_ATTR_TOTAL_SIZE(sizeof(UI32_T)); /* PSAMPLE_ATTR_GROUP_SEQ */
+
+ data_len = NETIF_NL_GET_ATTR_TOTAL_SIZE(ptr_ori_skb->len);
+
+ if ((msg_hdr_len + NETIF_NL_GET_ATTR_TOTAL_SIZE(ptr_ori_skb->len)) > NETIF_NL_PSAMPLE_PKT_LEN_MAX)
+ {
+ data_len = NETIF_NL_PSAMPLE_PKT_LEN_MAX - msg_hdr_len - NLA_HDRLEN - NLA_ALIGNTO;
+ }
+ else
+ {
+ data_len = ptr_ori_skb->len;
+ }
+
+ ptr_nl_skb = NETIF_NL_ALLOC_SKB(NETIF_NL_GET_ATTR_TOTAL_SIZE(data_len) + msg_hdr_len);
+ if (NULL != ptr_nl_skb)
+ {
+ /* to create a netlink msg header (cmd=0) */
+ ptr_nl_hdr = NETIF_NL_SET_SKB_ATTR_HDR(ptr_nl_skb, ptr_nl_family, 0, 0);
+ if (NULL != ptr_nl_hdr)
+ {
+ /* obtain the intf index for the igr_port */
+ igr_intf_idx = ptr_ori_skb->dev->ifindex;
+ NETIF_NL_SET_16_BIT_ATTR(ptr_nl_skb, NETIF_NL_PSAMPLE_ATTR_IIFINDEX,
+ (UI16_T)igr_intf_idx);
+
+ /* meta header */
+ /* use the igr port id as the index for the database to get sample rate */
+ ptr_priv = netdev_priv(ptr_ori_skb->dev);
+ intf_id = ptr_priv->port;
+ rate = NETIF_NL_GET_INTF_IGR_SAMPLE_RATE(intf_id);
+ NETIF_NL_SET_32_BIT_ATTR(ptr_nl_skb, NETIF_NL_PSAMPLE_ATTR_SAMPLE_RATE, rate);
+ NETIF_NL_SET_32_BIT_ATTR(ptr_nl_skb, NETIF_NL_PSAMPLE_ATTR_ORIGSIZE, data_len);
+ NETIF_NL_SET_32_BIT_ATTR(ptr_nl_skb, NETIF_NL_PSAMPLE_ATTR_SAMPLE_GROUP,
+ NETIF_NL_PSAMPLE_DFLT_USR_GROUP_ID);
+ NETIF_NL_SET_32_BIT_ATTR(ptr_nl_skb, NETIF_NL_PSAMPLE_ATTR_GROUP_SEQ, ptr_cb->seq_num);
+ ptr_cb->seq_num++;
+
+ /* data */
+ ptr_nl_attr = (struct nlattr *)skb_put(ptr_nl_skb, NETIF_NL_GET_ATTR_TOTAL_SIZE(data_len));
+ ptr_nl_attr->nla_type = NETIF_NL_PSAMPLE_ATTR_DATA;
+ /* get the attr size without padding, since it's the last one */
+ ptr_nl_attr->nla_len = NETIF_NL_GET_ATTR_SIZE(data_len);
+ skb_copy_bits(ptr_ori_skb, 0, nla_data(ptr_nl_attr), data_len);
+
+ NETIF_NL_END_SKB_ATTR_HDR(ptr_nl_skb, ptr_nl_hdr);
+ }
+ else
+ {
+ rc = NPS_E_OTHERS;
+ }
+ }
+ else
+ {
+ rc = NPS_E_OTHERS;
+ }
+
+ *pptr_nl_skb = ptr_nl_skb;
+
+ return (rc);
+}
+
+NPS_ERROR_NO_T
+_netif_nl_allocNetlinkSkb(
+ NETIF_NL_CB_T *ptr_cb,
+ NETIF_NL_FAMILY_T *ptr_nl_family,
+ struct sk_buff *ptr_ori_skb,
+ struct sk_buff **pptr_nl_skb)
+{
+ NPS_ERROR_NO_T rc = NPS_E_OK;
+
+ /* need to fill specific skb header format */
+ if (NETIF_NL_FAMILY_IS_PSAMPLE(ptr_nl_family))
+ {
+ rc = _netif_nl_allocPsampleSkb(ptr_cb, ptr_nl_family,
+ ptr_ori_skb, pptr_nl_skb);
+ if (NPS_E_OK != rc)
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[DBG] alloc netlink skb failed\n");
+ }
+ }
+ else
+ {
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "[DBG] unknown netlink family\n");
+ rc = NPS_E_OTHERS;
+ }
+
+ return (rc);
+}
+
+NPS_ERROR_NO_T
+_netif_nl_sendNetlinkSkb(
+ NETIF_NL_FAMILY_T *ptr_nl_family,
+ UI32_T nl_mcgrp_id,
+ struct sk_buff *ptr_nl_skb)
+{
+ int ret;
+ NPS_ERROR_NO_T rc;
+
+ ret = NETIF_NL_SEND_PKT(ptr_nl_family, nl_mcgrp_id, ptr_nl_skb);
+ if (0 == ret)
+ {
+ rc = NPS_E_OK;
+ }
+ else
+ {
+ /* in errno_base.h, #define ESRCH 3 : No such process */
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK,
+ "send skb to mc group failed, ret=%d\n", ret);
+ rc = NPS_E_OTHERS;
+ }
+
+ return (rc);
+}
+
+void
+_netif_nl_freeNetlinkSkb(
+ struct sk_buff *ptr_nl_skb)
+{
+ NETIF_NL_DBG(NETIF_NL_DBG_NETLINK, "[DBG] free nl skb\n");
+ NETIF_NL_FREE_SKB(ptr_nl_skb);
+}
+
+NPS_ERROR_NO_T
+_netif_nl_forwardPkt(
+ NETIF_NL_CB_T *ptr_cb,
+ NETIF_NL_RX_DST_NETLINK_T *ptr_nl_dest,
+ struct sk_buff *ptr_ori_skb)
+{
+ struct sk_buff *ptr_nl_skb = NULL;
+ NETIF_NL_FAMILY_T *ptr_nl_family;
+ UI32_T nl_mcgrp_id;
+ NPS_ERROR_NO_T rc;
+
+ rc = _netif_nl_getFamilyByName(ptr_cb, ptr_nl_dest->name,
+ &ptr_nl_family);
+ if (NPS_E_OK == rc)
+ {
+ rc = _netif_nl_getMcgrpIdByName(ptr_nl_family, ptr_nl_dest->mc_group_name,
+ &nl_mcgrp_id);
+ if (NPS_E_OK == rc)
+ {
+ rc = _netif_nl_allocNetlinkSkb(ptr_cb, ptr_nl_family,
+ ptr_ori_skb, &ptr_nl_skb);
+ if (NPS_E_OK == rc)
+ {
+ rc = _netif_nl_sendNetlinkSkb(ptr_nl_family, nl_mcgrp_id,
+ ptr_nl_skb);
+ if (NPS_E_OK != rc)
+ {
+ /* _netif_nl_freeNetlinkSkb(ptr_nl_skb); */
+ }
+ }
+ }
+ }
+
+ return (rc);
+}
+
+NPS_ERROR_NO_T
+netif_nl_rxSkb(
+ const UI32_T unit,
+ struct sk_buff *ptr_skb,
+ void *ptr_cookie)
+{
+ NETIF_NL_CB_T *ptr_cb = &_netif_nl_cb;
+
+ NETIF_NL_RX_DST_NETLINK_T *ptr_nl_dest;
+ NPS_ERROR_NO_T rc;
+
+ ptr_nl_dest = (NETIF_NL_RX_DST_NETLINK_T *)ptr_cookie;
+
+ /* send the packet to netlink mcgroup */
+ rc = _netif_nl_forwardPkt(ptr_cb, ptr_nl_dest, ptr_skb);
+
+ /* need to free the original skb anyway */
+ osal_skb_free(ptr_skb);
+
+ return (rc);
+}
+
+NPS_ERROR_NO_T
+netif_nl_init(void)
+{
+ osal_memset(&_netif_nl_cb, 0x0, sizeof(NETIF_NL_CB_T));
+
+ return (NPS_E_OK);
+}
+
+NPS_ERROR_NO_T
+netif_nl_deinit(void)
+{
+ return (NPS_E_OK);
+}
+
diff --git a/platform/nephos/nephos-modules/modules/src/netif_osal.c b/platform/nephos/nephos-modules/modules/src/netif_osal.c
index 15599e3a0aa0..51af7fcb3ad9 100755
--- a/platform/nephos/nephos-modules/modules/src/netif_osal.c
+++ b/platform/nephos/nephos-modules/modules/src/netif_osal.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/platform/nephos/nephos-modules/modules/src/netif_perf.c b/platform/nephos/nephos-modules/modules/src/netif_perf.c
index 18606d6d25d4..11dd03b58eb5 100755
--- a/platform/nephos/nephos-modules/modules/src/netif_perf.c
+++ b/platform/nephos/nephos-modules/modules/src/netif_perf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/platform/nephos/nephos-modules/modules/src/osal_isymbol.c b/platform/nephos/nephos-modules/modules/src/osal_isymbol.c
index c23cc70bed23..f908c2325966 100755
--- a/platform/nephos/nephos-modules/modules/src/osal_isymbol.c
+++ b/platform/nephos/nephos-modules/modules/src/osal_isymbol.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/platform/nephos/nephos-modules/modules/src/osal_mdc.c b/platform/nephos/nephos-modules/modules/src/osal_mdc.c
index 3dad3173ac79..d0a25e48fc32 100755
--- a/platform/nephos/nephos-modules/modules/src/osal_mdc.c
+++ b/platform/nephos/nephos-modules/modules/src/osal_mdc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Nephos, Inc.
+/* Copyright (C) 2020 MediaTek, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -37,7 +37,7 @@
#include
#include
#include
-
+#include
#include